Jetty.project: JPMS Support

Created on 9 Feb 2018  ·  172Comments  ·  Source: eclipse/jetty.project

This can be a root issue for ongoing efforts for Jetty to support JPMS features in Java.

Jetty has had OSGi support for nigh on a decade and it is not something we can simply abandon in lieu of java adding on a module management system. While that community has made strides in integrating well with the JPMS mechanics at the point of this thread creation it has largely been up in the air as to what that should mean for the Jetty project itself.

Jetty 9.4.x supports the usage of Java 9 with the module system disabled and it remains to be seen what Jetty 10 will do with it. Lets have some discussion on this thread about that and maybe start getting this broken down a bit.

@guw We would welcome your input here as well as a historical user of jetty and osgi, your plans regarding jpms and what you might expect from jetty regarding it.

We also have @PashaTurok with #2189 as the first user requesting this support and there is some info in that issue.

Additionally, to set expectations this is not something that will happen overnight, especially since it seems that it will involve a fairly substantial review of the overall artifact layout of Jetty.

Enhancement

All 172 comments

@jmcc0nn3ll Could you explain

fairly substantial review of the overall artifact layout of Jetty.

If Jetty supports OSGi - then there are already modules (OSGi bundles). JPMS is like OSGi with, I would say, three main differences - no module lifecycle, nor package versioning, no extra framework between modules and JVM. For all our projects we used principle - existing OSGI bundle becomes JPMS module.

In a perfect world Artifact would equal Module but they serve different purposes. We worked through that in OSGI through copious amounts of carnage in manifest files. It remains to be seen what effect that has with jpms but it would be simplistic to think there is a trivial path forward where Artifact = OSGI Module = JPMS Module.

To correctly use a module system we really need use cases from users such as @pashaturok. Questions that we need to consider include:

  • why isn't the auto module handling of jetty sufficient? What are the features that it does not provide.
  • should jetty be one big module or many module? Should we match OSGI?
  • how are dependencies such as the servlet API to be handled? Should we make them modules or are others doing so?
  • what about 3rd party libraries like JSP? Do we wait until they are modules? So module them? Or make our own modules if them?

Since I've been called out, here are my two cents. :)

IMHO, mapping OSGi bundles 1:1 to Java modules does not make sense from a Jetty perspective. When working with Jetty in the OSGi world, I always found myself using at least a minimum set of multiple Jetty bundles (jars). The future Jetty layout should be re-thought. My personal preference clearly goes towards less individual, small pieces, less dependencies, less complexity.

FWIW, I think the currently Maven structure is more a reflection of the Jetty architecture then of the Jetty distribution, i.e. it exists to support architecture boundaries within the Jetty code base and not because of Jetty's distribution layout. Those jars have then been mapped to OSGi bundles 1:1. I don't think any other strategy has been applied when creating OSGi bundles.

Before defining Jetty modules, the use cases have to be defined. I doubt that there will be a one size fits all model. For example, the modules provided by Jetty might fit only a certain percentage of use cases. Consumers of Jetty should not be afraid of building their own modules out of Jetty classes. I understand this is difficult currently as there is no convenient tooling yet.

There is currently also no answer to how EE next is going to deal with and define modules. For example, will there be a Servlet spec module? Are application servers supposed to depend on the Servlet spec module or are they supposed to provide the Servlet API as part of an application server module?

You also have to keep in mind, that dependencies between Java modules are hard wired to a module name, i.e. a web application with a dependency on a "Jetty" module will likely not run in Tomcat.

Last but not least, there is another aspect of JPMS that is part of JPMS support but currently completely undefined: layers. Layers become important when dealing with conflicting module dependencies. From a Jetty (and EE next) perspective, this could be web application loading. But then again, it's very, very unclear currently, if a future "application server" will still host multiple different web applications or if any such concept is discarded.

@guw About layers I gave my variant here https://github.com/eclipse/jetty.project/issues/2189 . I thought and came to conclusion that using separate layer for every site is the best solution - all modules of every site are independent (we can have N sites) and besides it is possible to create and destroy layers dynamically. It is very interesting what others think about such approach.
Note - I use term "site" but not "web application" as I consider the following situation- site includes two modules - front.war (web application) and logic.jar (that provides JPMS services to web application). Obviously, that logic.jar I want to use and for non web applications. By the way, when I tried to create layer with .war archive JPMS didn't want to do it - as I understand it wants only .jar

@PashaTurok Clearly, the concept of "site" seems very specific in the context of a specific use case. Thus, it needs to be defined as well, i.e. is site a reachable endpoint or does it resemble something that we today know as "war"? But then again, in a service scenario ("micro service" deployment), layers may not be wanted at all - not even a single one.

Thus, I think before deciding about what to _implement_, I'd like to see a discussion first about what is _needed_ and what is _reasonable_.

@guw I think now it is not very important how to name it. If you don't like site, lets call it web-resource or web-x, or domain or xxx.web. What important is to understand that this web-resource consists not only of web application archive (.war) but also of additional JPMS modules that, as I understand, and it is very important, must be outside .war.

@PashaTurok I'm not hooked on a specific name. Again, the concept of defining layers which combine modules outside of war with a war seems one of the many possibilities. As with class loaders, there is some "inherited" visibility that is given. However, I cannot decide whether Jetty should implement all possible options now or wait for some discussion to happen in the EE4J context.

FWIW, I think it makes sense to start small and allow consumers defining their own composition of JPMS modules including Jetty. This is similar to running Jetty inside an OSGi container as a bundle. If there is an agreement on how to slice the modules then this could be implemented. Any consumer can then define it's own loader as well as layer structure.

Could anyone say when this issue will approximately be resolved? In what version?

@PashaTurok We've not landed on any specific date or version for this yet. As @jmcc0nn3ll said, this is not a small change and will require significant effort to get up and running. Additionally, as @gregw pointed out, there are several questions we still need answers to in the long run. I know these are not things you can answer but will have to be dealt with regardless.

@WalkerWatch Thank you for your answer. I know that it is not small change, but I don't see any movement, that's why I asked about time. Or maybe I am wrong, maybe the issue is discussed somewhere else. To tell the truth I would like to see JPMS support in the nearest future as Java 9 released more then half a year ago.

"As of today, JPMS is a pain for library authors"
http://blog.joda.org/2018/03/jpms-negative-benefits.html

@sbordet Thank you for the provided link. The red line is The problem is that other projects will depend on your library. By not adopting JPMS at all, or with serious delay, you block those projects from progressing in their modularization.

@PashaTurok there are numerous red lines. From having to require Java 9+ as a baseline (can't do), to keep Android compatibility (a must), to get the work done (lots of work, negative benefits).
You see your red line, we see ours. It will be done, eventually. Feel free to produce a pull request. Thanks.

@sbordet Thank you for your comment. I agree that you see your red lines and I see mine.

About your suggestion to produce a pull request I can say, that I suggested to make jpms modules as 1:1 to osgi modules as we did in all our products. But my suggestion was not accepted. I know nothing about jetty architecture and its structure and obvious it will take me a lot of time to start to do something. This is the first. The second I, as thousands users of jetty, have to spend time on my own projects and don't have time even for it. That's why I can't take part in jetty development.

In my posts I try to express the user needs about JPMS support feature and try to understand approximate time about this feature. For example, if someone says it will be resolved in 5-7 years I will understand that I should look for another solution. I think, I've expressed my idea. Thanks.

Currently, the entire JavaEE project is going through the process of migrating to the Eclipse Foundation and being rebranded JakartaEE which is the new future of all of those specifications (Gunner referred to this above as EE4J). Once that lengthy process is off the ground they will be re-releasing the current specifications under the new letterhead so making sure we deal with that as elegantly as possible is probably one of the larger priorities we have. Coupled with finalizing the websocket refactoring, supporting the accelerated releases of Java itself and pushing other elements in the project towards the release of Jetty 10 all vying for priority the fact that you still remain the only person at the time of comment that has outright asked for this support may be an indication that the support you are seeking may not land in the short term. Now if we start getting a slew of people on this thread or another, be it end user, other projects or a client, expressing frustration with lack of support then that would be clear indication we need to move faster on the issue. As it stands there isn't a fire here and I don't see us rushing to support JPMS in the short term. Do we want to support it? Yes, absolutely. Are we feeling a massive need that it has to be in the next month or two? Not particularly.

Anyway, as you said "_The problem is that other projects will depend on your library. By not adopting JPMS at all, or with serious delay, you block those projects from progressing in their modularization._". We want to hear from those projects and what their expectations are in how they want to work with Jetty through JPMS. If you have been in contact with them expressing similar concerns then by all means send them our way or point us at their having issues.

+1 in the hopes there are others out there... Was looking for a quick embedded WebSocket server to run in my tests and I get a slew of module jetty.* reads package from both module A and B:

Error:java: module jetty.server reads package javax.websocket from both javax.websocket.client.api and javax.websocket.api

Also, really hoping to see more core/base libraries move so that running compact jlink builds are possible. Currently jlink doesn't allow automatic module names.

@jamespedwards42 can you detail how you would use a JPMS Jetty (e.g. just embed it in your application, use with jlink, etc.) ?
What is it that using JPMS will give you that you cannot do it with normal classpath ?

As said previously, knowing how people would use a JPMS'd Jetty will help us drive the effort.

I ask also because I went to conferences and spoke to expert on the matter (book authors and conference speakers), and we struggle to find a reason to move to JPMS modules.
We also could not find any project of the size/structure of Jetty that is doing the effort.

The latest report from Maven Central shows that basically nobody is moving to modules - apart a couple of logging frameworks.

Also, the JAXB module that will be removed in JDK 11 has a module-info.java, but the whole thing is broken - so having a module-info.java in the jar does not mean that the module is usable.

Honestly, does not look good for JPMS modules for applications.
They are good for the JDK, but that's about it.

I can be convinced otherwise, but I need some strong evidence or a killer use case, something where it would be clearly evident that a JPMS Jetty far outweigh its classpath counterpart.

Honestly, does not look good for JPMS modules for applications. They are good for the JDK, but that's about it.

Sorry, I can't agree with that. It seems to me, that you never used OSGi and didn't see the advantages of modular frameworks. JPMS is like OSGi but, of course, with some differences. You can take a look how many libraries are OSGi compliant. We can even say, that it is difficult to find a library that is not for OSGi.

By the way, Jetty is also OSGi compliant. Following your logic, there is no sense in it.

I see several reasons, why there are not so many projects that moved to JPMS: 1) a lot of projects can work as auto modules without any problems (Jetty, unfortunately can't). 2) not all developers learned this technology yet 3) this is new technology and not much time has passed.

@sbordet I felt inclined to post my desire for modules because of the following statement by @jmcc0nn3ll

Now if we start getting a slew of people on this thread or another, be it end user, other projects or a client, expressing frustration with lack of support then that would be clear indication we need to move faster on the issue.

Yes, I would like be able to deploy minimal runtimes compiled by jlink that include jetty as a webserver. However, I don't think there is much of an objective argument there, unless it is for a client-side/GUI application or some kind of IOT application. Maybe there is an objective argument there around security and having a reduced attack surface, but I'm not sure, no expertise there.

If you want to try out incubator modules then you need to have your project build modularized. I've been building an application against the new HttpClient, jdk.incubator.httpclient, and now it will all be ready to go for JDK 11 with the module java.net.http.

I think it would encourage better development practices across the entire ecosystem because developers would be forced to take a look at all of the dependencies they are bringing in. Hopefully it would encourage developers to program against interfaces and use the ServiceLoader. For example, why do core libraries have dependencies on Gson or Jackson, etc? Develop against an interface and load your JsonSerializer service at runtime. You shouldn't force your users into Jackson. Allow them to choose the Jackson module at runtime. Go look at libraries put out by respected organizations such as Amazon and even Google for interacting with database services, it is crazy that they have these forced dependencies.

I agree that larger projects such as jetty should not be the first movers, but it would be nice if they would help put the pressure on their core dependencies.

If anyone else is trying to get Jetty working as an automatic module. The dependency setup discussed in this blog post worked for me: https://itnext.io/writing-a-web-socket-server-with-embedded-jetty-46fe9ab1c435

@jamespedwards42 thanks for your feedback :+1:

@jamespedwards42 wrote:

Develop against an interface and load your JsonSerializer service at runtime.

It is not that simple, though, and it's a common case in Jetty too.

Say for example that you want to format your JSON with nice indents when you serialize an object.
How do you tell your JsonSerializer interface this?

You may add a setter method on it (setPrettyPrint(boolean)), but it quickly becomes a _fat_ interface with potentially a lot of setters when you only need String serialize(Object).
And these setters can only be those common to all implementations (or - yuck - throw/ignore when called and not supported).

Perhaps a builder? Well, it must be a Jackson-specific builder, though; so we are back at depending from a specific library directly.

How about a single configure(Map<String, Object> settings) method in the JsonSerializer interface? That works, but you lose your type safety.

What about XML/Properties file, _à la_ JPA? Again type safety lost.

CDI-style annotations? Isn't it similar to setters case, with the complication of combinatorial explosions of different configurations and custom annotations?

Many Jetty modules have a similar dilemma: we would like to hide certain implementation classes, but how can we expose their configurability without exporting the implementation class as well?

Ok so we just export everything in the JPMS module file. But how's that any different than the classpath then? Sure, jlink. And that's it.

That's why we want to collect from the community how they intend to use modules.

The line that we'll draw when we hide certain classes and export others can only be moved in one direction (that of exporting more classes) and may potentially break people that downgrade their Jetty version, for whatever reason (tried Jetty version N, does not work for me, downgrade to N-1, can't compile anymore).
If we decide to _not_ draw the line and export everything (e.g. automatic modules), we can never go back.

Hi @sbordet ,

IMHO you are overreacting about JPMS, it is not broken, it is already been evaluated (takes time to companies and developers evaluate) and it is already started to be used by enterprise products.

I know that JPMS is not very well supported yet by many popular libraries, but that doesn't mean it's broken, actually, the core libraries like Jetty should support it in order to dependent projects migrate to JPMS.

Besides the logical resolution of classpath hell (now we will call it module hell), there are more reasons to migrate to JPMS as described here: https://medium.com/criciumadev/java-10-migration-5d853f5b5f7e

One thing to take into the consideration is that many many enterprises run its applications in Docker containers as uber/fat jars with all dependencies in a single JVM like my company does with hundreds of Java applications.

To be honest, Jetty is the only major servlet provider we use that doesn't support basic JPMS yet.

We can run Spring Boot 2 applications with Undertow or Tomcat without any issue using JPMS very smoothly (no classpath), so they are the recommended choice now.

This becomes the sweet spot for JPMS, where we can leverage of jlink to create a custom JRE with only needed modules, so we don't need to load Swing/AWT classes for example, and make the application bootstrap faster and reduce memory consumption.

One thing I want to emphasise is that JPMS support can come in phases, no need to have full compliance.

I have a list to start:

  1. Add Automatic Module Names into all artifacts (#2127), so we don't have module names conflicts.
  2. Ensure packages aren't duplicated across artifacts, so we don't have module exports conflicts.
  3. Refactor Jetty classloader/jar/war/etc. detection to be aware of JPMS and scan files accordingly.
  4. Update dependencies to be Java 9+ compatible (ASM, etc.)
  5. Create a getting started documentation to list supported features, getting started and know issues.

After fixing all the items on this list, Jetty will be JPMS compatible and can be used in Java modular projects, while still have compatibility with older JDKs (1.7, etc.) because no module descriptor is required.

I want to offer some contribution to help with this issue. Probably testing and documenting, as I don't know the Jetty architecture or code base.

@panga We are certainly interested in taking reasonable steps to ensure we don't clash with JPMS, even if we are not yet ready to fully embrace it.

However, the concern is that if we take a wrong step, then we make be committed to a wrong path. See @sbordet 's concern about going down the automatic module name path. If we do that, are we then committed to not change any of our APIs because they are now part of the public API of our modules?

@gregw,

I understand you guys are concerned about API breaking changes because of JPMS, but there's a fact that you need to keep in mind:

Every JAR has already a Automatic Module Name generated by JVM (not stable & weird names) with all exported packages, just like it works today in JDK < 9.

So, what prevents Jetty to be JPMS compatible, making automatic module names stable, update thirdparty dependencies and be JPMS aware when doing some stuff like classloading/Unsafe/Reflection ? (remember that all packages are already exported by default).

The changes described above absolutely doesn't break anything on existing API and doesn't even need a major version to be released.

If first class JPMS support is really needed in future (JDK 11+), you want to embrace it, rethink of architecture and modules, private/public packages, etc. Them probably a major version would be released with JDK 9+ requirements and possibly with breaking changes.

That's not what I'm asking to do here or in near future.

@panga, what use or benefit do you have by running jars as automodules (either via manifest or via JVM) that you cannot have with classpath?

Would be great if you can explain with a clear example "I want to do this, and I cannot do it unless I use modules".
Have not found a single one so far.

Breaking everybody when we'll decide to go with proper modules is not something that people will like, especially when there's no way back.

Not to mention that we will need to change all Jetty module names since there is no versioning.

Your blog entry is like many others that show how to move to modules, like many others show how incredibly complicated that is (well, just follow 10-15 bullets of instructions and dodge all the quirks/bugs present in libraries that you need), and like many others the main question remains "what benefits do I have"? The answer is, like many others, zero.

You cannot use jlink, you cannot leverage modules for hiding implementation classes from libraries, I have not yet seen proof of any reduced jvm footprint or faster jvm starts. I'll be interested if you have pointers to real data, possibly not "hello world" examples, compared with proper classpath usage.

Thanks!

what use or benefit do you have by running jars as automodules (either via manifest or via JVM) that you cannot have with classpath?

You can't deal with the fact that JPMS is there and can be used and will be used, whatever is the reason.

Breaking everybody when we'll decide to go with proper modules is not something that people will like, especially when there's no way back.
Not to mention that we will need to change all Jetty module names since there is no versioning.

There's no _breaking_ if you support both classpath and modulepath with multi-release jars.

Your blog entry is like many others that show how to move to modules, like many others show how incredibly complicated that is (well, just follow 10-15 bullets of instructions and dodge all the quirks/bugs present in libraries that you need), and like many others the main question remains "what benefits do I have"? The answer is, like many others, zero.

The workarounds are temporary while thirdparty dependencies doesn't act properly to this call https://dzone.com/articles/automatic-module-name-calling-all-java-library-maintainers

Also, you can see the benefits by yourself executing the sample REST + JPA from my sample tutorial, and even this little application has perceptible benefits in memory and startup.

Please see this presentation:
https://www.slideshare.net/leonardozanivan/qconsp-2018-java-module-system

You cannot use jlink, you cannot leverage modules for hiding implementation classes from libraries, I have not yet seen proof of any reduced jvm footprint or faster jvm starts. I'll be interested if you have pointers to real data, possibly not "hello world" examples, compared with proper classpath usage.

The assumption that jlink can't be used is wrong, I'm already using it my own Java projects and with this maven plugin (https://github.com/moditect/moditect) I can fix thirdparty dependencies modules that are slow to update themselves.

@panga I failed to persuade them, but hoped that you would succeed. But it seems that you failed either.

@PashaTurok funny you should say this today.
We've been getting briefed today by @sbordet about his discussions on JPMS with others at the JCrete conference last week.
JPMS will happen, but we have to stage it right.

@joakime Good news! I am waiting this so long and need so much that started to feel it at the level of space currents.

In previous posts I suggested to create separate JPMS layer for every web application (web application = 1..N JPMS modules) as it allows to separate modules between web applications + class isolation. Alan Bateman suggests the same - see his comment here.

FTR, an option is to make a uber-jar with inside all Jetty code, and be that uber-jar a single JPMS module.
That I guess it's easy and quick. With time, we can split it.

Alternatively, we can start with the current status (i.e. everything exported), and then progressively hide over major releases (which for Jetty means the second number, e.g. 9.4 -> 9.5).

"The right way"(TM) would be to hide as much as possible and then export as needed, but it's a gigantic work.

Define "all Jetty code".
Some code is incompatible with each other and cannot be co-mingled in the same uber-jar. (eg: the various session managers)

The code is incompatible at runtime, but as long as it's in different packages we can certainly pack all Jetty code (meaning all sources of all modules) in a single uber-jar, no?

@sbordet correct, you can "ship" it all in one big jar as a single module.

Do you have a list of Jetty Java packages you consider "api"? Maybe you can start with exporting just those?

Tracking progress.

Trying to JPMS jetty-util and found that it depends on javax.servlet:javax.servlet-api (because of MultiPartInputStreamParser).

While we can get rid of MultiPartInputStreamParser in jetty-util (as we have an alternative implementation in jetty-http), there is no JPMS module for javax.servlet, so we are already completely stuck (as jetty-http would be the next Jetty module we'll try to JPMS-ify).

If anyone knows if there is a repackaging of javax.servlet as a JPMS module, otherwise we will need to create one, perhaps under org.mortbay as we did in the past.

Chances that JakartaEE will provide one in the short term are probably slim.

@sbordet Could you explain what is the problem with javax.sevlet? If I understand you correctly you can't find JPMS module that contains javax.servlet. If so, then we solved this problem by using "pure" javax.servlet:javax.servlet-api as automatic module. See here.

@gregw repackaging javax.servlet would be a pain (e.g. we would need to change the dependency in Jetty's main POM as well). You have any insights on when Jakarta EE will release javax.servlet and whether it will be a JPMS module?

@PashaTurok can you be more specific?

Jetty needs to do this:

module org.eclipse.jetty.<some> {
    ...
    requires javax.servlet;
    ...
}

How did you solve this?

I am currently not in office. But this is an example from someone's project https://github.com/faljse/webyoucam/blob/master/module-info.java

@PashaTurok this is what Maven says:

[WARNING] * Required filename-based automodules detected. Please don't publish this project to a public artifact repository! *

@sbordet As I understand this warning appears because of using automatic modules. So it will appear until all used dependencies become normal JPMS module. If I am right all jars will become JPMS modules about in 10, 20 or more years. If you don't like this warning you can 1) wait official javax.servlet.api JPMS module (not the nearest future) 2) create own JPMS module. But I would use automatic module, at least now as it is according to all JPMS specifications.

@PashaTurok I am already using javax.servlet-api as an automatic module.
Perhaps we go for 1 :grin:

@sbordet Sorry, I didn't understand you. Do you want to wait for official javax.servlet.api JPMS module?

@PashaTurok I would really like you to explain what advantages you will have running Jetty (if we implement the Jetty modules with Automatic-Module-Name) in the module-path versus running Jetty in the class-path.

As far as I can tell there is none.

When I said "we go for 1" I was joking :smile:

@sbordet the advantage of running Jetty in module-path versus running in the class-hell-path is that there's no hell in modules and the dependencies are linked during the boot time.

For Jetty project itself, it might make no sense, but it does in most of the commercial/enterprise projects I work.

I use Jetty project as an engine/framework, so I expect it to be used in many different use cases.

@sbordet About advantages. 1)It is not about module-path vs class-path. It is about modularization and modularization advantages. JPMS is a simple module framework like OSGi. The main difference is that OSGi is more dynamic (you can start/stop/uninstall certain modules) and JPMS is more static - when layer is created it is impossible to change any modules of the layer. In this meaning jetty modularization is advantage for you - developers of jetty as it allows achieve high cohesion and low coupling. 2) advantage for us (users) - JPMS and its layers allow to create different interesting configurations but all these interesting configurations can be used only with JPMS modules. For example we have module environment (100% using of JPMS) and we build all our applications using this environment.

We're leaning towards Automatic-Module-Name as we cannot see any other viable way given the current status of JPMS adoption - cannot write a proper module-info.java for the Jetty modules.

We will get this in a branch out of the current 9.4.x, will you guys be able to test it?

@sbordet I agree with Automatic-Module-Name approach for initial transition, but in next versions Jetty can also write module-info.java in multi-release jars, so it can run in JDK 8 and 9+ at the same time.

Besides that, Servlet scanning & mapping strategies might be changed to work correctly with module-path and reflection restrictions...

Yes, I can test this new branch with an existing application using JPMS.

@sbordet We will try to test with our products. The only problem is that our web products use Weld that is not JPMS yet (see my issue https://issues.jboss.org/browse/WELD-2493?_sscc=t). At least we will try to make them work together.

@panga I don't understand how multi-release jars are in the picture here. They are for alternate implementations of certain classes, and they don't support non-classes multi-releases (e.g config files like services etc.).

The version of Jetty that can write a proper module-info.java is when we will be able to properly specify dependencies e.g. to javax.servlet.api - which may happen years from now given the current speed of adoption of JPMS modules.

@panga some support for module-path should be there already, see #1933 and #1978 and related.
We will need you guys to do some iterations of testing to cover your cases.

@joakime @gregw we should also modify the standalone start mechanism, by adding maybe a --jpms option that puts all the Jetty jars in the module-path rather than the class-path. Thoughts?

@panga I don't understand how multi-release jars are in the picture here. They are for alternate implementations of certain classes, and they don't support non-classes multi-releases (e.g config files like services etc.).

Not exactly, multi-release jars support classes, resources and module-info.class.
I agree with you that a good quality module-info can take years to be ready.
References:
http://openjdk.java.net/jeps/238
https://blog.codefx.org/tools/multi-release-jars-multiple-java-versions/

@panga some support for module-path should be there already, see #1933 and #1978 and related.
We will need you guys to do some iterations of testing to cover your cases.

Great! #1978 is a must for me.

@PashaTurok, what exactly you need from weld?
I was able to make it work in version 3.0.5.Final with the patches I've submitted.
See my sample: https://github.com/panga/hammock-jpms

FTR: why we leaned towards Automatic-Module-Name.

First tried to JPMS-ify jetty-util. Using jdeps it's easy to find all dependencies and first problem is that there is no JPMS for javax.servlet:javax.servlet-api.

This is required by MultiPartInputStreamParser that has been deprecated and moved to jetty-http.
Even if we remove this class, we will have the same issue for the jetty-http module.
[As a side note, jetty-http may then require to be split in 3: a common, a client-only and a server-only module].

Trying to Maven compile with a non-JPMS jar in the module-path yields a Maven warning

Required filename-based automodules detected. Please don't publish
this project to a public artifact repository!

Dependencies for jetty-util are of the kind:

module org.eclipse.jetty.util {
    ...
    requires static org.slf4j;
    ...
}

requires static is necessary because if an application does not use the Jetty logging classes, it would not require to depend on SLF4J.

However, when we try to run the jetty-util tests via Maven, the test fails because they try to load SLF4J classes but cannot.

So far we have 2 showstoppers for real JPMS modules:

  • The Maven compiler warning
  • The Maven Surefire problem while running the tests

The first may take years to be resolved; the second may just be a Maven issue and may be promptly fixed.

Going for Automatic-Module-Name instead will push the problem to application developers, but for basic usage they may be able to get Jetty embedded running on the module-path.

Note that users are already able to run Jetty embedded from the module-path: just put the Jetty jars into the module-path, and the JVM will automatically convert them to modules.
Therefore we don't need to do anything, per se.

Adding Automatic-Module-Name to Jetty jars will only lock the module name, rather than using the jar name.
We are going for module names of the form org.eclipse.jetty.*, and not jetty.*.

Err, this Maven warning is new to me!

Regarding Surefire, yes it has some problems with JPMS, I expect them to be resolved soon.

Automatic-Module-Name is a good start, the module names will be stable for future use of module-info.

Expanding on Simone's summary, we also discussed how the module-info.java for a module didn't play particularly well with the test cases themselves. Maven conventions have the test cases under the same packages as the main artifacts classes and putting another module-info.java file under the same package under src/test/java gives angry warnings. Conceptionally the tests themselves are an application usage of the original artifact so it sort of makes sense that tests would/should have their own module-info.java to define the execution environment, like the slf4j example Simone gave. I am not aware of any updated conventions for the test situation but if anyone can point to some or have some anecdotes you are welcome to share!

The Maven Surefire issue related to running tests with requires static:
https://issues.apache.org/jira/browse/SUREFIRE-1563

@panga @PashaTurok out of curiosity, you can already run Jetty on the module-path as each Jetty jar will be converted to a module by the JVM, although the module names will be of the form jetty.*; if you do that, do you see other problems or everything just works?

Point being that the more details we know about things that people do when running Jetty as JPMS modules, the more we can fix things.

For early adopters, Automatic-Module-Name is now specified in the MANIFEST in branch jetty-9.4.x-2191-jpms.
Checkout the branch, build it with mvn install -DskipTests and try it out.

@sbordet I opened this issue because I had this problem and @joakime 's suggestion. I don't know if that problem is solved now.

I renamed the branch to jetty-9.4.x-2191-jpms_automatic_module_name, and it's now based on 9.4.13-SNAPSHOT.

Apparently IntelliJ is not yet able to run tests using properly the module-path, see https://youtrack.jetbrains.com/issue/IDEA-171419.

Given the current status of tooling around JPMS modules, I wonder how you guys are even able to write an application with JPMS module, unless you don't test it, don't use common build tools, etc.
You all do compile/test with custom tools that support JPMS?

I'm giving module-info.java another chance, but I'm stuck with failing tests that do:
Foo.class.getResource("/"), that with module-path returns null while returns a URL on class-path.

@sbordet About Foo.class.getResource("/") I would suggest to formulate a full question on SO - I think you will get the answer faster.

@PashaTurok I know the answer already. The question is how could you guys ever work with JPMS modules.

@sbordet We use gedit and javac. This is joke, of course. We use netbeans 9 beta (although it has really annoying bugs when working with JPMS) as IDE and maven as building system. We don't have any custom building tools for JPMS. Could you explain what is the problem?

Module jetty-http needs to load one of its own configuration files. It does:

MimeTypes.class.getClassLoader().getResourceAsStream(resource);

But now we need Module.getResourceAsStream(resource).

Ok, so make a ResourceUtils class in jetty-util so that we can hide behind it whether we are on the class-path and use Class or ClassLoader, or we are in the module-path and use Module, to get the resource stream.

But because now module jetty-util is loading from jetty-http, we need jetty-http to open the "package" (aka directory) from where the resource is loaded.

I am trying a proper JPMS module version (with module-info.java) and I was able to start Jetty as a standalone server with HTTP/2.

The startup times are:

  • with class-path
2018-09-03 16:44:33.924:INFO:oejs.Server:main: Started @474ms
  • with module-path
2018-09-03 16:39:29.978:INFO:oejs.Server:main: Started @1588ms

So running Jetty on the module-path gets us a 3x hit on startup.

@panga do you have or know about _actual data_ properly measured that explains in detail why modules should be faster to startup? Because from this initial test (surely not rigorous, but still) does not look good (e.g. our test suite that starts a Jetty server for almost every test will take ~1 s x ~1000 tests = ~20 minutes more to run).

@sbordet, not sure why the startup time is so slow, in all my tests with JPMS with both OpenJDK and OpenJ9 implementations I got faster(or equal) startup times in small web applications.

Can I use jetty-9.4.x-2191-jpms branch for testing that?
Can you provide me your sample app & JDK version you are using ?

@panga Can you comment this issue. It is interesting to hear your opinion.

@panga @PashaTurok have you been able to test the automatic module names in branch jetty-9.4.x-2191-jpms_automatic_module_name?

@sbordet No, I did nothing, as I saw that there was no answer to @panga question Can I use jetty-9.4.x-2191-jpms branch for testing that and thought it is not ready yet. Please, try to support two-way communication. So, is this jetty-9.4.x-2191-jpms_automatic_module_name branch ready for testing?

@PashaTurok yes branch jetty-9.4.x-2191-jpms_automatic_module_name is ready for testing.

@sbordet I am trying to test web application. This is how I do it.
I create JPMS layer and add to it the following modules:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <module file="me.pavel.webserver.core-0.1.0-SNAPSHOT.jar"/>

Please, note, that war file I don't add to this layer. To run jetty I use the following code:

        Server server = new Server( 8080 );
        WebAppContext webapp = new WebAppContext();
        webapp.setContextPath( "/" );
        File warFile = new File(
                "/home/Pavel/WebServerJettyJpms/jar/temp-0.1.0-SNAPSHOT.war" );
        if (!warFile.exists())
        {
            throw new RuntimeException( "Unable to find WAR File: "
                    + warFile.getAbsolutePath() );
        }
        webapp.setWar( warFile.getAbsolutePath() );
        webapp.setExtractWAR(true);
        webapp.setAttribute(
                "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$" );
        server.setHandler( webapp );
        server.start();
        server.dumpStdErr();

The server starts (I can access it 127.0.0.1:8080) and I don't have any problems with the speed (it starts fast). However, my web application is not deployed. I get:

java.lang.ClassNotFoundException: org.eclipse.jetty.webapp.WebInfConfiguration
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
    at java.base/jdk.internal.loader.Loader.loadClass(Loader.java:561)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
    at [email protected]/org.eclipse.jetty.util.Loader.loadClass(Loader.java:65)
    at [email protected]/org.eclipse.jetty.webapp.WebAppContext.loadConfigurations(WebAppContext.java:1035)
    at [email protected]/org.eclipse.jetty.webapp.WebAppContext.preConfigure(WebAppContext.java:473)
    at [email protected]/org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:544)
    at [email protected]/org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at [email protected]/org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:138)
    at [email protected]/org.eclipse.jetty.server.Server.start(Server.java:416)
    at [email protected]/org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:108)
    at [email protected]/org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
    at [email protected]/org.eclipse.jetty.server.Server.doStart(Server.java:383)
    at [email protected]/org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)

Do I do something wrong or this is a bug?

Can you please include the full command line that you use to start Jetty?

The JPMS layer for Jetty is created by our JPMS environment Alpha. This script starts alpha:

#!/bin/bash
ROOT_PATH="$(dirname "$0")/.."
#These are alpha modules.
modules=(
    com.organization.mix.slf4j-api-1.7.25.jar
    com.organization.mix.slf4j-simple-1.7.25.jar
    com.organization.kit.core-0.2.0-SNAPSHOT.jar
    com.organization.kit.jpms-0.2.0-SNAPSHOT.jar
    com.organization.alpha.core-0.3.0-SNAPSHOT.jar
)

MODULE_PATH=""
for m in "${modules[@]}"
do
    MODULE_PATH=${MODULE_PATH}:"$ROOT_PATH/jar/${m}"
done

/opt/jdk-9/bin/java \
    -Xdebug -Xrunjdwp:transport=dt_socket,address=7500,server=y,suspend=n \
    -Dorg.slf4j.simpleLogger.showDateTime=true \
    -Dorg.slf4j.simpleLogger.dateTimeFormat="yyyy-MM-dd HH:mm:ss:SSS" \
    -Dcom.organization.alpha.core.logging-level=debug \
    -Dcom.organization.alpha.core.logging-destination=console \
    -Dcom.organization.alpha.core.root-path="$ROOT_PATH" \
    -Dcom.organization.alpha.core.components="com.organization.alpha.server-0.3.0, com.organization.alpha.client-0.3.0" \
    -Dcom.organization.alpha.rct.script="./start.script" \
    -Djavax.net.ssl.keyStore="$ROOT_PATH/bin/client.jks" \
    -Djavax.net.ssl.keyStorePassword=client-keystore-password \
    -Djavax.net.ssl.trustStore="$ROOT_PATH/bin/client.jts" \
    -Djavax.net.ssl.trustStorePassword=client-truststore-password \
    -Djava.security.policy="$ROOT_PATH/bin/policy.ssl" \
    -Djava.net.preferIPv4Stack=true \
    --add-modules ALL-DEFAULT --module-path $MODULE_PATH \
    -m com.organization.alpha.core/com.organization.alpha.core.internal.Launcher

Jetty layer is created with one classloader as described here https://docs.oracle.com/javase/9/docs/api/index.html?java/lang/ModuleLayer.html

@sbordet Maybe the list of modules for boot and jetty layers (got by ModuleLayer API) can help:

Boot layer modules:
module slf4j.api
module oracle.desktop
module jdk.internal.opt
module java.xml
module jdk.crypto.ec
module java.scripting
module slf4.simple
module jdk.management.agent
module jdk.naming.rmi
module java.instrument
module oracle.net
module java.management
module jdk.attach
module java.desktop
module jdk.security.jgss
module jdk.jconsole
module jdk.javaws
module java.management.rmi
module java.logging
module jdk.security.auth
module jdk.jartool
module jdk.editpad
module jdk.jfr
module jdk.internal.ed
module jdk.jdeps
module jdk.snmp
module jdk.internal.jvmstat
module jdk.scripting.nashorn
module jdk.jlink
module jdk.naming.dns
module java.xml.crypto
module java.base
module jdk.plugin
module jdk.unsupported
module jdk.compiler
module java.rmi
module javafx.base
module jdk.jstatd
module jdk.management.cmm
module javafx.media
module jdk.deploy
module jdk.sctp
module java.security.jgss
module java.sql.rowset
module jdk.dynalink
module javafx.graphics
module javafx.swing
module jdk.accessibility
module com.organization.alpha.core
module javafx.fxml
module javafx.controls
module java.prefs
module jdk.packager.services
module jdk.plugin.dom
module jdk.management.resource
module jdk.management.jfr
module java.se
module java.datatransfer
module com.organization.kit.jpms
module jdk.charsets
module jdk.zipfs
module jdk.packager
module jdk.crypto.cryptoki
module javafx.web
module jdk.jshell
module java.smartcardio
module java.jnlp
module jdk.javadoc
module jdk.management
module jdk.internal.le
module java.naming
module jdk.jsobject
module jdk.httpserver
module jdk.net
module jdk.localedata
module jdk.xml.dom
module java.sql
module com.organization.kit.core
module java.compiler
module jdk.jdi
module jdk.jdwp.agent
module java.security.sasl

Jetty layer modules:
module org.eclipse.jetty.servlet
module org.eclipse.jetty.security
module javax.servlet.api
module org.eclipse.jetty.webapp
module org.eclipse.jetty.util
module com.organization.webserver.core
module org.eclipse.jetty.server
module org.eclipse.jetty.xml
module org.eclipse.jetty.servlets
module org.eclipse.jetty.http
module org.eclipse.jetty.io

@PashaTurok we found an issue when starting Jetty, and we pushed a fix to this branch, so please try the latest code on this branch.
With this fix, we are able to start Jetty on the module path and deploy a web application to $JETTY_BASE/webapps/.

/tmp/jpms$ java -jar $JETTY_HOME/start.jar --add-to-start=http,deploy
/tmp/jpms$ cp $JETTY_HOME/demo-base/webapps/async-rest.war webapps/
/tmp/jpms$ java --module-path $JETTY_HOME/lib/:$JETTY_HOME/start.jar -m org.eclipse.jetty.start/org.eclipse.jetty.start.Main
...
2018-09-17 19:28:30.608:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@50f6ac94{Async REST Webservice Example,/async-rest,[file:///tmp/jetty-0.0.0.0-8080-async-rest.war-_async-rest-any-16846749093019213314.dir/webapp/, jar:file:///tmp/jetty-0.0.0.0-8080-async-rest.war-_async-rest-any-16846749093019213314.dir/webapp/WEB-INF/lib/example-async-rest-jar-9.4.13-SNAPSHOT.jar!/META-INF/resources],AVAILABLE}{/async-rest.war}

I think that you are getting the ClassNotFoundException because you don't set the thread context classloader properly.
You should call Thread.setContextClassLoader(...) with the classloader you used to load the Jetty layer, just before invoking your class, so that when Jetty's Server starts, it will have the right classloader to load classes with.

Let us know how it goes.

@sbordet Ok, I built the latest code. So the results. I again create separate JPMS layer for jetty and add the following modules to it:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <module file="apache-jsp-8.5.24.2.jar"/>
    <module file="taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.eclipse.jdt.core-3.10.0.jar"/>
    <module file="com.organization.webserver.core-0.1.0-SNAPSHOT.jar"/>

The war file I put on classpath (-cp /home/Pavel/.....war). Pure servlets seem to work. However, I could not make JSP work. When in my TestServlet I do

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/dynamic/about.jsp").include(request, response);
    }

and there is a jsp file (webapp/dynamic/about.jsp) jetty gives me only blank page without any errors in logs. Only this message:

2018-09-17 22:19:56:467 [qtp856980901-30] INFO org.eclipse.jetty.server.handler.ContextHandler.ROOT - No JSP support. Check that JSP jars are in lib/jsp and that the JSP option has been specified to start.jar

Do I do something wrong or the problem is in jetty?

Did you set the thread context classloader?

@sbordet Yes, it was my fault. Before starting jetty I set context classloader = jetty layer classloader and ClassNotFoundException was solved. Now I need to solve JSP problem.

@PashaTurok can you explain how did you choose the jar files that provide JSP support?
They do not match what Jetty provides by default, and that may be the cause of why JSP don't work.

Please look at what the standard Jetty distribution provides in JETTY_HOME/lib/apache-jsp/*.
You may also need what's in JETTY_HOME/lib/apache-jstl/*.

Since Jetty reuses the Apache JSP implementation, I'm not sure if they are JPMS compliant.

@sbordet Oh, I took them from pom. After your note I changed module list to :

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <!-- JSP -->
    <module file="org.eclipse.jdt.ecj-3.12.3.jar"/>
    <module file="org.eclipse.jetty.apache-jsp-9.4.12.v20180830.jar"/>
    <module file="org.mortbay.jasper.apache-el-8.5.24.2.jar"/>
    <module file="org.mortbay.jasper.apache-jsp-8.5.24.2.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-spec-1.2.5.jar"/>
    <module file="com.orgn.webserver.core-0.1.0-SNAPSHOT.jar"/>

Now jetty gives me the following ouput in browser:

HTTP ERROR 500

Problem accessing /. Reason:

    Server Error

Caused by:

org.apache.jasper.JasperException: Unable to compile class for JSP
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:610)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:368)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NullPointerException
    at [email protected]/org.apache.jasper.JspCompilationContext.getTldResourcePath(JspCompilationContext.java:561)
    at [email protected]/org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:433)
    at [email protected]/org.apache.jasper.compiler.Parser.parseDirective(Parser.java:492)
    at [email protected]/org.apache.jasper.compiler.Parser.parseElements(Parser.java:1448)
    at [email protected]/org.apache.jasper.compiler.Parser.parse(Parser.java:145)
    at [email protected]/org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
    at [email protected]/org.apache.jasper.compiler.ParserController.parse(ParserController.java:105)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:203)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:374)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:351)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:335)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    ... 50 more

Caused by:

java.lang.NullPointerException
    at [email protected]/org.apache.jasper.JspCompilationContext.getTldResourcePath(JspCompilationContext.java:561)
    at [email protected]/org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:433)
    at [email protected]/org.apache.jasper.compiler.Parser.parseDirective(Parser.java:492)
    at [email protected]/org.apache.jasper.compiler.Parser.parseElements(Parser.java:1448)
    at [email protected]/org.apache.jasper.compiler.Parser.parse(Parser.java:145)
    at [email protected]/org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
    at [email protected]/org.apache.jasper.compiler.ParserController.parse(ParserController.java:105)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:203)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:374)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:351)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:335)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:368)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)

I don't want to solve this problem now, so I am trying to compile jsp at building time and added this plugin to pom of the war project:

           <plugin>
                <groupId>org.eclipse.jetty</groupId>
                 <artifactId>jetty-jspc-maven-plugin</artifactId>
                 <version>9.4.12.v20180830</version>
                 <executions>
                   <execution>
                     <id>jspc</id>
                     <goals>
                       <goal>jspc</goal>
                     </goals>
                     <configuration>
                     </configuration>
                   </execution>
                 </executions>
               </plugin>

But now I get

Compiling dynamic/about.jsp from includes=**\/*.jsp, **\/*.jspx excludes=**\/.svn\/**
At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

I don't see the jetty-schemas jar file, it's necessary for JSP compilation and TLDs to function.

I added jetty-schemas-4.0.1.jar to module list but it didn't help - the same error. Why I can't compile JPS using jetty-jspc-maven-plugin. Do I miss some configs?

@PashaTurok we fixed another issue with the apache-jsp JPMS module name. Please pull the latest code.

After that we were able to compile and run a JSP.

Make sure that you have in your Jetty layer the jars in $JETTY_HOME/lib/annotations/, in particular the ASM jars (which are proper JPMS modules) - you probably need to explicitly add them to the module graph via --add-modules.

/tmp/jpms$ java -jar $JETTY_HOME/start.jar --add-to-start=http,deploy,jsp

The line above is enough (with the latest code) to compile and run JSPs for us.

@sbordet Ok. After your commit a6abd0b I built jetty again and from that build I took ONLY two modules: apache-jsp-9.4.13-SNAPSHOT.jar, apache-jstl-9.4.13-SNAPSHOT.jar. All other JETTY modules I left from previous build. BTW asm is JPMS already. So now I have the following module list:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <!-- JSP -->
    <module file="org.eclipse.jdt.ecj-3.12.3.jar"/>
    <module file="org.eclipse.jetty.apache-jsp-9.4.12.v20180830.jar"/>
    <module file="org.mortbay.jasper.apache-el-8.5.24.2.jar"/>
    <module file="org.mortbay.jasper.apache-jsp-8.5.24.2.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-spec-1.2.5.jar"/>
    <module file="jetty-schemas-4.0.1.jar"/>
    <module file="apache-jsp-9.4.13-SNAPSHOT.jar"/>
    <module file="apache-jstl-9.4.13-SNAPSHOT.jar"/>
    <module file="asm-6.2.jar"/>
    <module file="asm-commons-6.2.jar"/>
    <module file="asm-analysis-6.2.jar"/>
    <module file="asm-tree-6.2.jar"/>
    <module file="javax.annotation-api-1.2.jar"/>
    <module file="com.orgz.webserver.core-0.1.0-SNAPSHOT.jar"/>

However, I get Caused by: java.lang.module.ResolutionException: Modules org.eclipse.jetty.apache.jsp and apache.jsp export package org.eclipse.jetty.apache.jsp to module org.mortbay.apache.jasper. Seems I added some extra modules or do something wrong. Maybe I should take from last build this module org.eclipse.jetty.apache-jsp instead of apache-jsp-9.4.13-SNAPSHOT but I can't find it.

Remove apache-jsp and apache-jstl jars.

@sbordet Removed. However, why then did you ask me to pull the last changes if I don't add any new module? Maybe I should update this org.eclipse.jetty.apache-jsp-9.4.12.v20180830.jar? In what subproject is it localed?

Now I have such result org.apache.jasper.JasperException: Unable to compile class for JSP at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:610) ....

@PashaTurok all jetty jars should be the same release level: you've got org.eclipse.jetty.apache-jsp-9.4.12.v20180830.jar, but it should be 9.4.13-SNAPSHOT. This artifact is built in the apache-jsp sub-module in the jetty repo.

Not that this is the cause of your problem, but be aware that as of 9.4.13-SNAPSHOT we have upgraded the org.mortbay.jasper.* jars to version 8.5.33, and org.eclipse.jdt.ecj jar to version 3.14.0.

As to the output you see when doing precompilation with the jetty-jspc-maven-plugin, that is a warning that jasper puts out any time it scans a jar that does not contain any tlds. It is harmless.

@janbartel Thank you for explanation, but still can't find org.eclipse.jetty.apache-jsp neither in jetty.project nor in maven repo. See this

Pavel@pavel-desktop:~/Temp/jetty.project/apache-jsp$ ls
pom.xml  src  target
Pavel@pavel-desktop:~/Temp/jetty.project/apache-jsp/target$ ls
apache-jsp-9.4.13-SNAPSHOT-config.jar  apache-jsp-9.4.13-SNAPSHOT-sources.jar  generated-sources           maven-status     pmd.xml
apache-jsp-9.4.13-SNAPSHOT.jar         archive-tmp                 maven-archiver              pmd
apache-jsp-9.4.13-SNAPSHOT-nolog.jar   classes                     maven-shared-archive-resources  pmd_logging_ruleset.xml
Pavel@pavel-desktop:~/.m2/repository/org/eclipse/jetty$ ls
aggregate    jetty-alpn-client  jetty-client        jetty-jaas   jetty-jspc-maven-plugin  jetty-quickstart  jetty-servlets   jetty-xml      websocket
alpn         jetty-alpn-parent  jetty-continuation  jetty-jaspi  jetty-parent         jetty-rewrite     jetty-util       orbit
apache-jsp   jetty-alpn-server  jetty-deploy        jetty-jmx    jetty-plus       jetty-security    jetty-util-ajax  osgi
apache-jstl  jetty-annotations  jetty-http      jetty-jndi   jetty-project        jetty-server      jetty-webapp     test-jetty-webapp
http2        jetty-ant      jetty-io        jetty-jsp    jetty-proxy          jetty-servlet     jetty-websocket  toolchain

Could you say the path to org.eclipse.jetty.apache-jsp startting from jetty.project?

@PashaTurok the Jetty project has a module called apache-jsp that produces a jar called apache-jsp-9.4.13-SNAPSHOT.jar that used to have a wrong JPMS automatic module name - this was fixed in a6abd0b.

When the Jetty build creates the Jetty distribution, it renames the apache-jsp jar into $JETTY_HOME/lib/apache-jsp/org.eclipse.jetty.apache-jsp-9.4.13-SNAPSHOT.jar.

You can therefore use either only apache-jsp-9.4.13-SNAPSHOT.jar or only org.eclipse.jetty.apache-jsp-9.4.13-SNAPSHOT.jar as you prefer, but like @janbartel said, they must have the same version as all the other Jetty jars (in your case 9.4.13-SNAPSHOT).

I would prefer if you use the jars from the Jetty distribution (therefore under $JETTY_HOME/lib/), so that we are sure that A) you took them all and B) we are on the same page when we compare our way or running Jetty from the module path and your way of running Jetty from a JPMS layer created by your framework.

@sbordet Thank you for you detailed explanation. I would never guess that you change file name. Maybe you should't do this :). Now I've built the latest jetty jars (for now I don't rename apache-jsp-9.4.13-SNAPSHOT.jar). This is my module list:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <!-- JSP -->
    <module file="apache-jsp-9.4.13-SNAPSHOT.jar"/>
    <module file="apache-jstl-9.4.13-SNAPSHOT.jar"/>
    <module file="org.eclipse.jdt.ecj-3.12.3.jar"/>
    <module file="apache-el-8.5.33.jar"/>
    <module file="apache-jsp-8.5.33.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-spec-1.2.5.jar"/>
    <module file="jetty-schemas-4.0.1.jar"/>
    <module file="ecj-3.14.0.jar"/>
    <module file="asm-6.2.jar"/>
    <module file="asm-commons-6.2.jar"/>
    <module file="asm-analysis-6.2.jar"/>
    <module file="asm-tree-6.2.jar"/>
    <module file="javax.annotation-api-1.2.jar"/>
    <module file="com.orgz.webserver.core-0.1.0-SNAPSHOT.jar" activator-enabled="true"/>

This is what I get in browser:

HTTP ERROR 500

Problem accessing /. Reason:

    Server Error

Caused by:

org.apache.jasper.JasperException: Unable to compile class for JSP
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:610)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:382)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NullPointerException
    at [email protected]/org.apache.jasper.JspCompilationContext.getTldResourcePath(JspCompilationContext.java:561)
    at [email protected]/org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:430)
    at [email protected]/org.apache.jasper.compiler.Parser.parseDirective(Parser.java:489)
    at [email protected]/org.apache.jasper.compiler.Parser.parseElements(Parser.java:1445)
    at [email protected]/org.apache.jasper.compiler.Parser.parse(Parser.java:144)
    at [email protected]/org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
    at [email protected]/org.apache.jasper.compiler.ParserController.parse(ParserController.java:105)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:202)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    ... 50 more

Caused by:

java.lang.NullPointerException
    at [email protected]/org.apache.jasper.JspCompilationContext.getTldResourcePath(JspCompilationContext.java:561)
    at [email protected]/org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:430)
    at [email protected]/org.apache.jasper.compiler.Parser.parseDirective(Parser.java:489)
    at [email protected]/org.apache.jasper.compiler.Parser.parseElements(Parser.java:1445)
    at [email protected]/org.apache.jasper.compiler.Parser.parse(Parser.java:144)
    at [email protected]/org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
    at [email protected]/org.apache.jasper.compiler.ParserController.parse(ParserController.java:105)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:202)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:382)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)

@PashaTurok you need also jetty-annotations-<ver>.jar.

@sbordet I added. This is my module list now:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <!-- JSP -->
    <module file="apache-jsp-9.4.13-SNAPSHOT.jar"/>
    <module file="apache-jstl-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-annotations-9.4.13-SNAPSHOT.jar"/>
    <module file="org.eclipse.jdt.ecj-3.12.3.jar"/>
    <module file="apache-el-8.5.33.jar"/>
    <module file="apache-jsp-8.5.33.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-spec-1.2.5.jar"/>
    <module file="jetty-schemas-4.0.1.jar"/>
    <module file="ecj-3.14.0.jar"/>
    <module file="asm-6.2.jar"/>
    <module file="asm-commons-6.2.jar"/>
    <module file="asm-analysis-6.2.jar"/>
    <module file="asm-tree-6.2.jar"/>
    <module file="javax.annotation-api-1.2.jar"/>
    <module file="com.orgz.webserver.core-0.1.0-SNAPSHOT.jar" activator-enabled="true"/>

However, I have the same error - nothing changed.

@sbordet java.lang.NullPointerException at [email protected]/org.apache.jasper.JspCompilationContext.getTldResourcePath(JspCompilationContext.java:561) appears if I add to my jsp file this <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>. If I don't add I have exception in another place:

HTTP ERROR 500

Problem accessing /. Reason:

    Server Error

Caused by:

org.apache.jasper.JasperException: Unable to compile class for JSP
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:610)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:382)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NullPointerException
    at [email protected]/org.apache.jasper.compiler.Validator$ValidateVisitor.<init>(Validator.java:516)
    at [email protected]/org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1854)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:220)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    ... 50 more

Caused by:

java.lang.NullPointerException
    at [email protected]/org.apache.jasper.compiler.Validator$ValidateVisitor.<init>(Validator.java:516)
    at [email protected]/org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1854)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:220)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:382)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)

@PashaTurok if your JSP is just:

<% System.err.println("HELLO"); %>

does it work?

@sbordet No, this is what I have:

HTTP ERROR 500

Problem accessing /. Reason:

    Server Error

Caused by:

org.apache.jasper.JasperException: Unable to compile class for JSP
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:610)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:382)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NullPointerException
    at [email protected]/org.apache.jasper.compiler.Validator$ValidateVisitor.<init>(Validator.java:516)
    at [email protected]/org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1854)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:220)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    ... 50 more

Caused by:

java.lang.NullPointerException
    at [email protected]/org.apache.jasper.compiler.Validator$ValidateVisitor.<init>(Validator.java:516)
    at [email protected]/org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1854)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:220)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:382)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)

Powered by Jetty:// 9.4.z-SNAPSHOT 

Please add: jetty-plus-<v>.jar, jetty-jndi-<v>.jar.

@sbordet Added. This is my current module list:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <!-- JSP -->
    <module file="apache-jsp-9.4.13-SNAPSHOT.jar"/>
    <module file="apache-jstl-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-annotations-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-jndi-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-plus-9.4.13-SNAPSHOT.jar"/>
    <module file="org.eclipse.jdt.ecj-3.12.3.jar"/>
    <module file="apache-el-8.5.33.jar"/>
    <module file="apache-jsp-8.5.33.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-spec-1.2.5.jar"/>
    <module file="jetty-schemas-4.0.1.jar"/>
    <module file="ecj-3.14.0.jar"/>
    <module file="asm-6.2.jar"/>
    <module file="asm-commons-6.2.jar"/>
    <module file="asm-analysis-6.2.jar"/>
    <module file="asm-tree-6.2.jar"/>
    <module file="javax.annotation-api-1.2.jar"/>
    <module file="com.orgz.webserver.core-0.1.0-SNAPSHOT.jar" activator-enabled="true"/>

This is the content of my JSP file :

<% System.err.println("HELLO"); %>

This is what I get:

HTTP ERROR 500

Problem accessing /. Reason:

    Server Error

Caused by:

org.apache.jasper.JasperException: Unable to compile class for JSP
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:610)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:382)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NullPointerException
    at [email protected]/org.apache.jasper.compiler.Validator$ValidateVisitor.<init>(Validator.java:516)
    at [email protected]/org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1854)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:220)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    ... 50 more

Caused by:

java.lang.NullPointerException
    at [email protected]/org.apache.jasper.compiler.Validator$ValidateVisitor.<init>(Validator.java:516)
    at [email protected]/org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1854)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:220)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:350)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:334)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:382)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)

@PashaTurok you seem to have the same configuration as us, and we can compile the simplest JSP (`<% System.err... %>) - although we cannot if it contains a taglib directive - I'm working on it.

Rather than adding jars, can you please have your framework point to the $JETTY_HOME/lib/:$JETTY_HOME/lib/annotations/:$JETTY_HOME/lib/apache-jsp/: directories rather than adding the jars one by one?

Let's also try for now only the simplest JSP, that we know works for us.

Ok. Then let me ask several questions about building jetty distribution. When I do in jetty.project mvn install I can build only about 30% of th project. When I do in jetty.project/jetty-distribution mnv install I also get build failure. Is this normal? Maybe I build jetty distribution wrong.

@PashaTurok you should do this:

$ git clone https://github.com/eclipse/jetty.project.git
$ cd jetty.project
$ git checkout jetty-9.4.x-2191-jpms_automatic_module_name
$ mvn clean install -DskipTests

After that the Jetty distribution is in jetty-distribution/target/distribution/.
This directory is what I refer to when I say "Jetty distribution" or - equivalently - $JETTY_HOME.

BTW I was able to compile a JSP with a taglib directive (<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>) - previously I forgot to add $JETTY_HOME/lib/apache-jstl to the module-path.

In conclusions, it works for us, so we just need to figure out what's different for you.

@sbordet I've built distribution. I see that in jetty.project/jetty-distribution/target/distribution/lib/apache-jsp you use different versions. Your versions are:

org.eclipse.jdt.ecj-3.12.3.jar            org.mortbay.jasper.apache-el-8.5.24.2.jar
org.eclipse.jetty.apache-jsp-9.4.13-SNAPSHOT.jar  org.mortbay.jasper.apache-jsp-8.5.24.2.jar

but mine (after @ janbartel 's note ) are :

<module file="apache-el-8.5.33.jar"/>
<module file="apache-jsp-8.5.33.jar"/

Which should I use?

Please use the ones from the distribution.

@sbordet I am sorry, but it doesn't work. In order to group all jars I added comment from what folder they come from and sort them. I checked twice - every line (name, version etc). This is my module list:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <!-- JSP -->
    <!-- From jetty.project/jetty-distribution/target/distribution/lib/annotations -->
    <module file="asm-6.2.jar"/>
    <module file="asm-analysis-6.2.jar"/>
    <module file="asm-commons-6.2.jar"/>
    <module file="asm-tree-6.2.jar"/>
    <module file="javax.annotation-api-1.2.jar"/>
    <!-- From jetty.project/jetty-distribution/target/distribution/lib/apache-jsp-->
    <module file="org.eclipse.jdt.ecj-3.12.3.jar"/>
    <module file="org.eclipse.jetty.apache-jsp-9.4.13-SNAPSHOT.jar"/>
    <module file="org.mortbay.jasper.apache-el-8.5.24.2.jar"/>
    <module file="org.mortbay.jasper.apache-jsp-8.5.24.2.jar"/>
    <!-- From jetty.project/jetty-distribution/target/distribution/lib/apache-jstl -->
    <module file="org.apache.taglibs.taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-spec-1.2.5.jar"/>
    <!-- From /jetty.project/jetty-distribution/target/distribution/lib --> 
    <module file="jetty-annotations-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-jndi-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-plus-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-schemas-3.1.jar"/>
    <module file="com.orgz.webserver.core-0.1.0-SNAPSHOT.jar" activator-enabled="true"/>

This is what I get:

HTTP ERROR 500

Problem accessing /. Reason:

    Server Error

Caused by:

org.apache.jasper.JasperException: Unable to compile class for JSP
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:610)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:368)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NullPointerException
    at [email protected]/org.apache.jasper.compiler.Validator$ValidateVisitor.<init>(Validator.java:516)
    at [email protected]/org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1854)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:221)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:374)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:351)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:335)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    ... 50 more

Caused by:

java.lang.NullPointerException
    at [email protected]/org.apache.jasper.compiler.Validator$ValidateVisitor.<init>(Validator.java:516)
    at [email protected]/org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1854)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:221)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:374)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:351)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:335)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:368)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:48)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:78)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)

Quick note.

<module file="org.mortbay.jasper.apache-el-8.5.24.2.jar"/>
<module file="org.mortbay.jasper.apache-jsp-8.5.24.2.jar"/>

Those are old.

They should be ...

<module file="org.mortbay.jasper.apache-el-8.5.33.jar"/>
<module file="org.mortbay.jasper.apache-jsp-8.5.33.jar"/>

Since you are getting a compiler error, perhaps you should switch from using ECJ to using the standard java compiler.
Removing the following will force standard java compiler to be used.

<module file="org.eclipse.jdt.ecj-3.12.3.jar"/>

What I don't know is how to setup a jpms module environment to allow standard java compiler usage.

I do as @sbordet said - I take from distro. See this

Pavel@pavel-desktop:~/Temp/jetty.project/jetty-distribution/target/distribution/lib/apache-jsp$ ls
org.eclipse.jdt.ecj-3.12.3.jar            org.mortbay.jasper.apache-el-8.5.24.2.jar
org.eclipse.jetty.apache-jsp-9.4.13-SNAPSHOT.jar  org.mortbay.jasper.apache-jsp-8.5.24.2.jar

@joakime we can run Jetty on the module path from the branch, so the JSP jar version is not relevant. Nor compiler jars.
Let's use the same things as the branch so that there is one less variable to this issue.

@PashaTurok I think it's now your embedded Jetty code that is missing things.

Please add:

Configuration.ClassList classlist = Configuration.ClassList
        .setServerDefault(server);

classlist.addBefore(
        "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
        "org.eclipse.jetty.annotations.AnnotationConfiguration"
);

This needs to be done before you start the Server instance.

Jetty features come with a *.mod file and possibly an associated jetty-*.xml file, for example mod and xml.

When you want to enable certain Jetty features such as JSP, you need to lookup the existing module and xml, and replicate their behavior.

In this particular case, jsp needs annotations and jetty-annotations.xml has that snippet of code that you are missing.

Let us know how it goes.

@sbordet Yes, you are right I added your code before starting server and I finally get my jsp page. However, this page works only without JSTL. When I add to JSP this:

<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core"%>
<c:out value = "Victory"/>

Then I get this :

HTTP ERROR 500

Problem accessing /. Reason:

    Server Error

Caused by:

org.apache.jasper.JasperException: The absolute uri: [http://java.sun.com/jsp/jstl/core] cannot be resolved in either web.xml or the jar files deployed with this application
    at [email protected]/org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:55)
    at [email protected]/org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:293)
    at [email protected]/org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:80)
    at [email protected]/org.apache.jasper.compiler.TagLibraryInfoImpl.generateTldResourcePath(TagLibraryInfoImpl.java:251)
    at [email protected]/org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:122)
    at [email protected]/org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:434)
    at [email protected]/org.apache.jasper.compiler.Parser.parseDirective(Parser.java:492)
    at [email protected]/org.apache.jasper.compiler.Parser.parseElements(Parser.java:1448)
    at [email protected]/org.apache.jasper.compiler.Parser.parse(Parser.java:145)
    at [email protected]/org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
    at [email protected]/org.apache.jasper.compiler.ParserController.parse(ParserController.java:105)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:203)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:374)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:351)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:335)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:368)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:124)
    at org.school.site.temp.TestServlet.processRequest(TestServlet.java:49)
    at org.school.site.temp.TestServlet.doGet(TestServlet.java:79)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:844)

I think that with JPMS the approach like :

Configuration.ClassList classlist = Configuration.ClassList
        .setServerDefault(server);

classlist.addBefore(
        "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
        "org.eclipse.jetty.annotations.AnnotationConfiguration"
);

must be deprecated. Because if you want any feature you must only add some module (to module path or layer). The existence of this module must prove the necessity of the feature. Again, this is my personal opinion.

Your problem with the JSTL directive is due to the fact that you need to put into the module-path the classes in $JETTY_HOME/lib/apache-jstl/.

@sbordet Sorry, I don't understand you. I did add the jar in that folder to my layer. This is my module list:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <!-- JSP -->
    <!-- From jetty.project/jetty-distribution/target/distribution/lib/annotations -->
    <module file="asm-6.2.jar"/>
    <module file="asm-analysis-6.2.jar"/>
    <module file="asm-commons-6.2.jar"/>
    <module file="asm-tree-6.2.jar"/>
    <module file="javax.annotation-api-1.2.jar"/>
    <!-- From jetty.project/jetty-distribution/target/distribution/lib/apache-jsp-->
    <module file="org.eclipse.jdt.ecj-3.12.3.jar"/>
    <module file="org.eclipse.jetty.apache-jsp-9.4.13-SNAPSHOT.jar"/>
    <module file="org.mortbay.jasper.apache-el-8.5.24.2.jar"/>
    <module file="org.mortbay.jasper.apache-jsp-8.5.24.2.jar"/>
    <!-- From jetty.project/jetty-distribution/target/distribution/lib/apache-jstl --> <!-- HERE -->
    <module file="org.apache.taglibs.taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-spec-1.2.5.jar"/>
    <!-- From /jetty.project/jetty-distribution/target/distribution/lib --> 
    <module file="jetty-annotations-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-jndi-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-plus-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-schemas-3.1.jar"/>
    <module file="com.orgz.webserver.core-0.1.0-SNAPSHOT.jar" activator-enabled="true"/>

And these are modules loaded to layer (via ModuleLayer API) :

module com.orgz.webserver.core
module org.mortbay.apache.jasper
module org.objectweb.asm.commons
module org.eclipse.jetty.annotations
module org.objectweb.asm
module jetty.schemas
module org.eclipse.jetty.servlet
module org.apache.taglibs.taglibs.standard.spec
module org.eclipse.jetty.servlets
module org.eclipse.jetty.apache.jsp
module org.eclipse.jetty.http
module org.eclipse.jetty.webapp
module org.eclipse.jdt.ecj
module org.eclipse.jetty.io
module org.eclipse.jetty.server
module org.eclipse.jetty.security
module javax.servlet.api
module org.eclipse.jetty.plus
module org.eclipse.jetty.jndi
module org.mortbay.apache.el
module org.eclipse.jetty.xml
module javax.annotation.api
module org.apache.taglibs.taglibs.standard.impl
module org.objectweb.asm.tree.analysis
module org.objectweb.asm.tree
module org.eclipse.jetty.util

The way Jetty starts in standalone mode is that the Jetty start module creates a URLClassLoader that loads all the server jars, and then scans the jars in WebInfConfiguration.findAndFilterContainerPaths().

The logic is:

  1. see if the classloader is a URLClassLoader and load jars from there; otherwise
  2. if JDK >= 9 parse java.class.path and load the jars from there; otherwise
  3. if JDK >= 9 parse jdk.module.path and load the jars from there.

I'm guessing that your framework won't do any of the above.

If Jetty can scan the jars, it will find the TLDs and your issue will be solved.

@sbordet Ok. Thank you for your explanation. Let's suppose I have layer with some modules loaded in it. Can I make jetty scan these modules to locate TLDs before starting jetty server?

@PashaTurok sure, just use a URLClassLoader to load the modules in your layer.

@sbordet Is there any API or code I could take as example? I ask as I know jetty architecture bad and can't understand how to do it having on hands only ModuleLayer.modules().

@PashaTurok it's actually the other way around. If you show me your code that creates the Layer and its ClassLoader, I can suggest what you can do. Is your framework available publicly?

What you're doing with Layers is not present in Jetty so there will be no example to look for.

I would use ModuleLayer.defineModules(Configuration cf, Function<String, ClassLoader> clf) that allows you to create a URLClassLoader to load the modules via the mapping function.
New territory for me too, so mine is just a guess, but from what I see it should work.

No, the framework is not available publicly. The layer is created this way:

ModuleLayer parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolveAndBind(finder, ModuleFinder.of(), moduleNames);
ClassLoader parentClassLoader = ClassLoader.getSystemClassLoader();
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, parentClassLoader);

This thread is getting long and difficult to follow. Let me offer a reset here:

Read the documentation at: http://www.eclipse.org/jetty/documentation/9.4.12.v20180830/configuring-jsp.html. Follow the links to worked code examples for writing a jetty embedded startup sequence that enables jsps. Pay close attention to the section of documentation that deals with setting up jstl.

The latest error you report indicates that jsp and jstl have not been set up correctly, specifically that jars containing the jstl tlds have not been scanned. Either the org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern has not been set to correctly reflect the names of the jar files that contain tlds, or you have not enabled annotations, which jsp relies on. Either way, please thoroughly read the documentation to which I've pointed.

Finally, enable DEBUG logging for org.eclipse.jetty.webapp.MetaInfConfiguration (or just the whole org.eclipse.jetty.webapp package) to see which, if any jars are being scanned for resources such as tlds.

@janbartel I don't think it's a setup issue.

@PashaTurok is playing with the ModuleLayer APIs so that the Jetty jars are not loaded by a URLClassLoader, they are not in the class-path and they are not in the module-path, but in a ModuleLayer class loader child of the system class loader.

The current Jetty code needs to scan the jars, but with that setup there is no way Jetty can, and that is the problem.
@PashaTurok just need to change the ModuleLayer class loader to be a URLClassLoader.

@sbordet This is the way I create ModuleLayer:

ModuleLayer layer = parent.defineModulesWithOneLoader(cf, parentClassLoader);

From javadoc

defineModulesWithOneLoader​(Configuration cf, ClassLoader parentLoader)
... This method creates one class loader and defines all modules to that class loader.

How can I change the ModuleLayer class loader to be a URLClassLoader?

@PashaTurok I did not try, but something like:

Set<URL> urls = moduleURLsFromXML();
URLClassLoader loader = new URLClassLoader(urls);
Configuration config = ...
ModuleLayer parent = ModuleLayer.boot();
ModuleLayer layer = parent.defineModules(config, moduleName -> loader);

Method moduleURLsFromXML() will derive file:/// URLs from your XML configuration where you define the Jetty modules (of which you have pasted examples in the comments above).

Once you have the URLs, the rest is trivial, you just call defineModules(...) instead of defineModulesWithOneLoader(...).

@sbordet Thank you for your help, but the code you provided doesn't work. When I create module as you described using loader I can't load any class, and get any resource. For example earlier this code worked module.getResourceAsStream("META-INF/MANIFEST.MF"); however, now it returns null.

@PashaTurok should you not be using ModuleReader to find resources?

@sbordet As I understand ModuleReader is used internally in ModuleReference at framework level. At application level I think module.getResourceAsStream must be used. I checked you code both with default ModuleFinder and WarModuleFinder.

@sbordet I still can not make jsp tags work. What should I do?

@PashaTurok JSTL tags do work.

It's just in your framework that don't work, right?
I'm guessing it's a behavioral change in the JDK that we can't do much about.

@sbordet I don't think that it is behavioral change in the JDK. Why if you deploy jetty modules in boot layer with module path then JSTL works, but if you deploy them in a custom layer and without module path JSTL doesn't work. It is strange, isn't it?

It's not strange, we went to the bottom of it, it's a ClassLoader behavior issue.

@sbordet Can you formulate the issue? I will try to find a solution. Does boot layer use URLClassLoader and custom not? Could you clear say - I will ask at SO?

TLDs are discovered by Jetty by looking up *.tld files in jars. We currently do this using JarFile in WebInfConfiguration.

We cannot use [Class|ClassLoader|Module]getResource*() because we don't know the name of the TLD descriptor, just that ends with *.tld.

So we need a way to scan JPMS modules to find TLDs without knowing their file name.

See if the work done here helps you: jetty-project/annotation-discovery#4.

JSP itself also uses org.apache.jasper.servlet.TldScanner to do it's own TLD lookups (put a breakpoint in TldScanner.scan() and watch what it also does/expects).

TLDScanner is kicked off from the javax.servlet.ServletContainerInitializer implementation org.apache.jasper.servlet.JasperInitializer.
Check the onStartup(Set<Class<?>> types, ServletContext context) method for how TLDScanner itself is initialized.

@joakime Thank you for your suggestion. Using debugger I am now trying to understand how these .tld's are found. But I don't see why org.apache.jasper.servlet.JasperInitializer implementation is used for javax.servlet.ServletContainerInitializer. I found file META-INF/services/javax.servlet.ServletContainerInitializer in org.eclipse.jetty.apache-jsp-9.4.13-SNAPSHOT.jar. The content of this file is org.eclipse.jetty.apache.jsp.JettyJasperInitializer but not org.apache.jasper.servlet.JasperInitializer. How to explain it?

JettyJasperInitializer extends from JasperInitializer

https://github.com/eclipse/jetty.project/blob/71a1801433b092c81ef22dc2453cb41c4eba92f2/apache-jsp/src/main/java/org/eclipse/jetty/apache/jsp/JettyJasperInitializer.java#L35-L40

javax.servlet.ServletContainerInitializer is one part of the servlet spec startup lifecycle (a complex beast when you start digging into it).

All implementations of javax.servlet.ServletContainerInitalizer are executed at the specific point in the servlet spec startup lifecycle for ServletContainerInitializers.

These implementations are found via the standard java.util.ServiceLoader mechanisms. (which uses the META-INF/services/<service-name> files you have discovered)

@sbordet , @joakime Thank you for your help. I finally could make my JSTL work. This is my solution (using ClassGraph)

       WebAppContext webapp = new WebAppContext();
        List<URL> tldUrls = new ArrayList<>();
        try (ScanResult scanResult = new ClassGraph().whitelistPaths("META-INF").scan()) {
            scanResult
                .getResourcesWithExtension("tld")
                .forEach((Resource res) -> {
                    try {
                        URL url = new URL("jar:" + res.getClasspathElementURL() + "!/" + res.getPath());
                        tldUrls.add(url);
                    } catch (MalformedURLException ex) {
                        ex.printStackTrace();
                    }
                });
        }
        webapp.setAttribute("org.eclipse.jetty.tlds", tldUrls);

Note: the "ClassGraph" that @PashaTurok is referring to is a library at https://github.com/classgraph/classgraph

@PashaTurok This line in your code:

URL url = new URL("jar:" + res.getClasspathElementURL() + "!/" + res.getPath());

Should be:

URL url = res.getURL();

I'm not sure that you need to prepend "jar:", but if you do, do something like:

URL url = new URL("jar:" + res.getURL());

Note that Resource URLs will have the jrt:/ URL scheme for system modules, and that may trip up some libraries (not relevant for your "tld" files, but it's worth pointing this out).

Also, rather than just recording the URLs of the tld files, if you plan to actually read these files, the fastest way to do this is through using the ClassGraph Resource or ResourceList APIs, since ClassGraph does a lot of work under the hood to optimize the reading of files no matter what the backing store is (directories, jars or modules), no matter how you want to access the file (InputStream, ByteBuffer or byte[]), and no matter which OS you are running on (Linux, Windows, Mac OS X).

re. this old comment:

"As of today, JPMS is a pain for library authors"
http://blog.joda.org/2018/03/jpms-negative-benefits.html

I solved this in ClassGraph by using the awesome Moditect library at build-time. I compile my code in JDK 7 compatibility mode, then I use Moditect to compile just the module-info.java into a module-info.class file (using ObjectWeb ASM) that is JDK9+-compatible.

Here is my Moditect rule:

https://github.com/classgraph/classgraph/blob/master/pom.xml#L89

And here is the src/moditect/module-info.java file (I chose to put this into its own directory in the project, but could have simply inlined it in the pom.xml file, using <moduleInfoSource> rather than <moduleInfoFile>):

https://github.com/classgraph/classgraph/blob/master/src/moditect/module-info.java

With this in place, ClassGraph runs just fine as a non-modular (classpath) jarfile in JDK 7+, or as a named module in JDK9+.

The only time this causes an issue is if you have another classpath scanner or linter on the classpath that is not JPMS-aware (a lot of older versions of scanners give an NPE or similar when they hit an invalid classfile; in the case of Android, the classfile linter complains during build) -- the module-info.class file is seen as invalid by most classfile binary parsers from pre-JDK9, and can even cause some of them to crash.

(Sorry, still catching up on some of this thread)... re:

We cannot use [Class|ClassLoader|Module]getResource*() because we don't know the name of the TLD descriptor, just that ends with *.tld.

So we need a way to scan JPMS modules to find TLDs without knowing their file name.

The ClassGraph Resource API, as used in @PashaTurok's example, is probably your best chance of doing this, since ClassGraph supports the widest possible number of ways of adding things to the classpath and module path, with a single consistent API:

https://github.com/classgraph/classgraph/wiki/Classpath-Specification-Mechanisms

I gave a more complete example here, for the case where you want to scan a single module:

https://github.com/jetty-project/annotation-discovery/issues/4#issuecomment-424121653

There was some discussion in other comments about how to discover classpath and module path elements. If they were added at launch, ClassGraph will detect them, and you can call new ClassGraph().getClasspathURLs() and/or new ClassGraph().getModules() to enumerate all classpath URLs and/or modules in visible layers.

If however you want to scan modules loaded dynamically using a custom URLClassLoader, and the scanning code is not itself running within that classloader, call ClassGraph#overrideClassLoaders(customURLClassLoader) or ClassGraph#addClassLoader(customURLClassLoader) before calling ClassGraph#scan() -- this will allow ClassGraph to see the dynamically-loaded classes.

FTR.

At Jetty startup, running on the module path, these messages are printed:

2018-09-25 19:53:23.904:WARN:oatud.DigesterFactory:main: The XML schema [XMLSchema.dtd] could not be found. This is very likely to break XML validation if XML validation is enabled.
...
2018-09-25 19:53:24.006:WARN:oatud.DigesterFactory:main: The XML schema [web-app_3_1.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
...

This is org.mortbay.jasper:apache-jsp:org.apache.tomcat.util.descriptor.DigesterFactory that tries to load XMLSchema.dtd and does not find it.

The way XMLSchema.dtd is searched is via ServletContext.class.getResource("resources/XMLSchema.dtd") and, if not found, via JspContext.class.getResource("resources/XMLSchema.dtd").

In JDK 11 Class.getResource() works in this way:

  1. Normalizes the name to javax/servlet/resources/XMLSchema.dtd
  2. Checks whether module java.servlet is open to the caller module org.mortbay.apache.jasper (so that the latter can read resources from the former); since both (for now) are automatic modules, this check passes.
  3. Calls BuiltinClassLoader.findResource(moduleName, resourceName); because moduleName is not null, the resource is not searched in the classpath, but just in the module.

Because javax/servlet/resources/XMLSchema.dtd is only searched in module java.servlet, it won't be found in other places that used to work, when searching the whole classpath.
In particular we have a copy in jetty-schemas-<version>.jar that is now not searched.

What we need to do is to patch the java.servlet module with jetty-schemas-<version>.jar.
This is now possible with the new [jpms] section available in *.mod files.

When Jetty runs on the module-path, there are a few things that needs to be corrected.

In particular:

  • Jetty standalone starts with only org.eclipse.jetty.xml as the root module; since currently the Jetty modules are automatic modules, when the XML files are executed and instantiate classes from other Jetty modules, they will be found; however, proper JPMS modules that Jetty classes depend on are not seen and must be manually added to the root modules.
  • As in the previous comment, some existing JPMS module needs to be patched by Jetty jars.
  • In general, we need a mechanism in the *.mod files to mimic the various Java command line options related to module configuration such as --add-modules, --patch-module, --add-opens, etc.

We introduce an option --jpms that generates the command line to run Jetty on the module-path.
We introduce an optional [jpms] section in *.mod files with the following format:

[jpms]
add-modules: <module name>(,<module name>)*
patch-module: <module>=<file>(:<file>)*
add-opens: <module>/<package>=<target-module>(,<target-module>)*
add-exports: <module>/<package>=<target-module>(,<target-module>)*
add-reads: <module>=<target-module>(,<target-module>)*

To start the demo-base shipped with the distribution, we need:

[ini]
--jpms

[jpms]
add-modules: java.sql,java.transaction,org.objectweb.asm
patch-module: servlet.api=${jetty.home}/lib/jetty-schemas-3.1.jar

And then Jetty can be started on the module-path via:

$ cd $JETTY_HOME/demo-base
$ java -jar ../start.jar --module=jpms

The [ini] section adds the --jpms option that tells Jetty to run on the module-path.
The [jpms] section adds the proper JPMS modules requires by the web applications in demo-base.

Module java.sql is needed to load class MockDataSource that extends javax.sql.DataSource.
Module java.transaction is needed to load class MockUserTransaction that extends javax.transaction.UserTransaction.

The patch-module directive is needed because of the problems explained two comments ago.

In addition, annotation.mod has been modified with this additional section:

[jpms]
add-modules: org.objectweb.asm

because AnnotationParser depends on ASM.

Also, webapp.mod has been modified with this additional section:

[jpms]
add-modules: java.instrument

because WebAppClassLoader catches java.lang.instrument.IllegalClassFormatException.

@gregw please review the last 3 comments above.

@sbordet I'm looking at this from 20,000 feet as I've not really got JPMS paged fully into my brain yet. So forgive any stupid comments.

I'm on board with the concept of patch-modules as packaging will never be perfect and being able to adjust modules is self evident by the existence of these mechanisms. The Jetty mod files feel like the right place to do this as they are documenting usages and our dependencies.

However, I'm a bit concerned about the need for [jpms] addModules:? Aren't we just duplicating dependency information? Are they dependencies of this module? If so isn't the whole point of JPMS is that dependencies can be declared so the jars of the current module should have their dependencies baked into their META_INF already? Surely such dependencies can be discovered rather than listed? Also if they are dependencies then perhaps they would be better listed in the [depends] section... like:

[depends]
   some-other-jetty-module
   jpms:some-java-module

Or rather than dependencies of this module are they libraries that using this module makes available? In which case surely they should be part of the [lib] section:

[lib]
   some-jetty.jar
   jpms:some-java-module

But again I'm not sure why they can't be discovered from the listed jars rather than configured here?

So again... I think it is good that we make JPMS modules mutable from jetty modules... but I don't think we should duplicate dependency hierarchies.

FTR, to answer @gregw we need the [jpms] section because we are dealing with automatic JPMS modules that cannot express their dependencies because they are lacking module-info.java.

@nicolaiparlog I would like a confirmation about how the module system work, because I could not find a clear statement about this.

Jetty uses automatic modules with Automatic-Module-Name, that are put in the module-path.

If module jetty.A loads a class from jetty.B, the class is loaded without problems.
If module jetty.A loads a class from org.objectweb.asm (that is a full blown, proper module-info.java module), then the ASM class is not found; to make it work I need --add-modules org.objectweb.asm.

Seems as if automatic modules in the module-path are all considered part of the _root modules_.

A slightly different use case: module jetty.A loads a class from jetty.B via reflection.
Again, no problem loading the class if jetty.B is an automatic module.
But again, failure to load the class if jetty.B is a proper module.

Is my assumption right that automatic modules are always part of the _root modules_?
Any other explanation? Thanks!

Disclaimer: I only read the comment mentioning me (because: lazy :wink:). If there's context I missed, let me know.

No, automatic modules are not always in the set of root modules. But as soon as module resolution encounters one automatic module, _all_ automatic modules are resolved. In short, it's "all or nothing" - you either get all automatic modules or none of them. Since Jetty is the application here, I assume you launch it with --module jetty.A (or some other module), which resolves one and hence all other automatic modules.

That leaves the question about its dependencies open:

  • You can place them on the module path, but then you have to --add-modules them (direct dependencies suffice, the others will be resolved on their own).
  • You can place them on the class path, but then you get no module system benefits.

Since you're seriously interacting with the module system, did you consider going all in and properly modularize your artifacts? Assuming you're not raising the baseline to Java 9 or later, you could create a multi-release JAR, thus keeping the module declaration out of the JAR's root class tree.

I just want to say I appreciate the work you are doing here! A majority of companies I have worked at deploy everything in docker containers which would benefit a lot from a small jlink runtime. This would improve deployment times because of smaller docker image downloads and better startup time. As well as smaller memory footprint which makes a difference when running many micro-services.

@nicolaiparlog

I only read the comment mentioning me

That's ok, I need only specific information :smiley:

But as soon as module resolution encounters one automatic module, all automatic modules are resolved.

Not sure if you use the word "resolved" here with a special meaning, but if I add to command line --show-module-resolution I don't see any of the Jetty automatic modules printed out.
If by "resolved" you mean "added to the set of root modules" then that would explain the behavior I'm seeing.

I assume you launch it with --module jetty.A, which resolves one and hence all other automatic modules.

I do exactly that.
To be more precise we do --module org.eclipse.jetty.xml/org.eclipse.jetty.xml.XmlConfiguration.
This XmlConfiguration class reads Jetty XML files that are similar to Spring XML files (actually, Jetty's were there before Spring's) in that they contain class name strings (from other Jetty modules) that are loaded and then objects instantiated.
This works perfectly fine _without_ having to add any --add-module option.

This is what was strange to me: if org.eclipse.jetty.xml is my only root module, and it's an automatic module so the JVM cannot figure out its dependencies, how can it load classes from other Jetty modules without --add-modules? That why I'm thinking that automatic modules are put in the root modules set (or at least it is as if they are - the behavior is indistinguishable).

So I still don't have a clear answer due to the meaning of the word "resolution" in your answer.

That leaves the question about its dependencies open: You can place them on the module path, but then you have to --add-modules them

This part of your answer confuses me, because most certainly I do not have to --add-modules any other module, _as long as they are automatic modules_; I do have to --add-modules proper modules such as java.instrument or org.objectweb.asm.
It is evident that automatic modules and proper modules are treated differently.

Since you're seriously interacting with the module system, did you consider going all in and properly modularize your artifacts?

Yes, but it requires a much larger effort (we talked about this, remember?) and it's currently scheduled for Jetty 10.x where we will require JDK 11 and we will have the Module APIs available for further usages.

With this particular issue we want to lock the Jetty JPMS module names; it's a trivial change to add Automatic-Module-Name in Jetty 9.4.x and does not require too many changes.

We also wanted to gather experience of what it means to run from the module-path for a Container that needs to do a lot of nasty things such as class annotation scanning, jar scanning for services and initializer classes, jar scanning for TLDs, web fragments, etc. etc.

The current HEAD of the branch where this work is done can already run Jetty from the module-path with JSP, JNDI, DataSource, etc. working well - which seems like nothing but was not trivial to figure out.

I have a (local) experimental branch where I am actually using module-info.java, and I can tell you it's a lot more work: we need to decide what to hide and what not, change packages to classes (possibly breaking people), figure out Maven compile and test extra options (e.g. Maven Compiler/Surefire plugins needing --add-modules and other options, see https://issues.apache.org/jira/browse/SUREFIRE-1563), etc.
Will be done, but later in Jetty 10.x.

Will appreciate if you can clear my doubts about automatic modules behaving differently from proper modules, and maybe a reference in the spec/code to this different behavior. Thanks!

Module Resolution

Not sure if you use the word "resolved" here with a special meaning, ...

Yes, it has a special meaning. Module resolution is the process where the module system takes the root modules and, one by one, resolves all its direct and transitive dependencies. From the best book about the module system :wink: :

ch03-module-resolution-short

(Full version & paywalled section.)

... but if I add to command line --show-module-resolution I don't see any of the Jetty automatic modules printed out.

That is odd. When I launch a demo application with a dependency on an automatic module with --show-module-resolution, I see the following:

monitor.rest requires spark.core file:///home/nipa/code/JPMS-Monitor/mods/spark.core.jar automatic

Note the automatic and the end. The only reason why you might not see this that I can come up with is that my initial module is an explicit one (i.e. with module-info.class) whereas yours is automatic, but I doubt that makes a difference.

how can it load classes from other Jetty modules without --add-modules?

Because when the module system resolves an automatic module's dependencies, it adds all other automatic modules to the module graph (and all automatic modules read one another).

That why I'm thinking that automatic modules are put in the root modules set

I'm pretty sure that's not the case. You can easily verify that:

  • create a small explicit module that reflectively loads a class from, say, Guava
  • place Guava's JAR on the module path
  • observe that the reflective call fails because Guava is not in the module graph (I predict; maybe I'm wrong)

Handling Dependencies

This part of your answer confuses me, because most certainly I do not have to --add-modules any other module, as long as they are _automatic modules_; I do have to --add-modules proper modules such as java.instrument or org.objectweb.asm.

You got it exactly right. Sorry for the confusion, I was distracted by --add-modules org.objectweb.asm and limited by thoughts (but not my sentences) to explicit modules. When I wrote "you have to add them with --add-modules" that only pertains to explicit modules because, as you correctly analyzed, automatic modules need not be added.

But! As soon as a dependency that you place on the module path gets modularized, it is no longer an automatic module and thus no longer added by itself. If users are allowed to drop in updates to your dependencies, then launch scripts will fail when they update to a modularized version. Furthermore, by placing all dependencies on the module path, you expose them all to module system checks without getting much benefit (since they aren't really modules). I would consider placing only your JARs (and maybe modularized dependencies) on the module path and leaving the rest on the class path.

Modularization Path

Yes, but it requires a much larger effort (we talked about this, remember?)

Yes, now I do. :blush: Squatting module names with 9.x and moving to modules in 10.x is a great approach! :+1:

@sbordet Can you say if you solved the problem with 2018-09-25 19:53:23.904:WARN:oatud.DigesterFactory:main: The XML schema [XMLSchema.dtd] could not be found. This is very likely to break XML validation if XML validation is enabled.?

@nicolaiparlog thanks for the detailed update, all clear now. The --show-module-resolution issue was my fault - I was issuing it on the wrong JVM. Now I can see automatic modules are resolved, similar to your example. Thanks!

@PashaTurok yes it's solved.

Since there was some discussion on multi-release jars earlier: @PashaTurok if you're still planning on using ClassGraph, you might be interested to know that I added support for multi-release jar scanning in version 4.2.3. If any META-INF/versions/X directories exist (for integers X greater than or equal to 9 and less than or equal to the running JVM version), then the directory X with the highest value less than or equal to the JVM version is used as the package root for scanning the jar.

@lukehutch Ok. Thank you. I will take a look.

@lukehutch took a look at your multi-release stuff, why didn't you just use the jvm built-in zipfs FileSystem?

@joakime because ClassGraph is supposed to be backwards-compatible all the way back to JDK7, so every call I have to make to APIs only available in JDK 8+ needs to be done through reflection, which is cumbersome. Also, I put a lot of work into highly parallelizing ZipFile scanning, and using zipfs (probably) can't achieve the same level of scalability. (ZipFile has a global per-instance lock around it -- I'm not sure if zipfs uses that, or reimplements unzipping from scratch, but it is unlikely that the Java libraries implemented the unzip code two separate times, so I'm guessing ClassGraph's unzip code is much faster than zipfs, because it creates one ZipFile instance per thread, which is the only way I am aware of that zipfile access can be parallelized in Java using the standard APIs.)

That said, if you're using JPMS, which is highly likely if you're using multi-release jars, the ClassGraph parallel ZipFile code is never even called, because ClassGraph calls the JPMS API through reflection, which internally uses zipfs. The JPMS API automatically handles multi-release masking (and removing the META-INF/versions/X prefix from resource paths), so ClassGraph doesn't need to do that for the module path scanning case either.

So really the code I put in place for multi-release jars is for a very specific usecase: including a multi-release jar on the traditional classpath (rather than the module path) when running on JDK 9+.

@lukehutch You suggested to replace

URL url = new URL("jar:" + res.getClasspathElementURL() + "!/" + res.getPath());
````
with:

URL url = new URL("jar:" + res.getURL());

Unfortunately it didn't work.
My code gives such result:

jar:file:/home/Pavel/Web%20Server/bin/./../jar/com.noname.temp.core-1.0.0.jar!/META-INF/tags/tags.tld

Your code this:

jar:file:/home/Pavel/Web%20Server/bin/./../jar/com.noname.temp.core-1.0.0.jar!META-INF/tags/tags.tld
```
See the difference before META-INF.

@sbordet I have two layers. On one I have jetty, on the second I have two modules - war module and jar module. Jar module contains tld files and tag implementations classes. Tags from jar module I use in war module.

This is stack:

2018-10-10 19:54:15:325 [qtp1062359567-39] ERROR com.noname.jar.core.mvc.JspView - There was an error processing file /dynamic/jsp/common.jsp
org.apache.jasper.JasperException: /dynamic/jsp/common.jsp (line: [19], column: [8]) Unable to load tag handler class [com.noname.jar.core.tags.IncludeAreaTag] for tag [t:includeArea]
    at [email protected]/org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:41)
    at [email protected]/org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:291)
    at [email protected]/org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:97)
    at [email protected]/org.apache.jasper.compiler.Parser.parseCustomTag(Parser.java:1244)
    at [email protected]/org.apache.jasper.compiler.Parser.parseElements(Parser.java:1473)
    at [email protected]/org.apache.jasper.compiler.Parser.parse(Parser.java:145)
    at [email protected]/org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
    at [email protected]/org.apache.jasper.compiler.ParserController.parse(ParserController.java:105)
    at [email protected]/org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:203)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:374)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:351)
    at [email protected]/org.apache.jasper.compiler.Compiler.compile(Compiler.java:335)
    at [email protected]/org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:595)
    at [email protected]/org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:368)
    at [email protected]/org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)
    at [email protected]/org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)
    at [email protected]/org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:112)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:542)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:129)
    at сom.noname.jar.core/com.noname.jar.core.mvc.JspView.renderFile(JspView.java:136)
    at сom.noname.jar.core/com.noname.jar.core.mvc.JspView.render(JspView.java:94)
    at сom.noname.jar.core/com.noname.jar.core.AbstractFrontController.processDynamicRequest(AbstractFrontController.java:194)
    at сom.noname.jar.core/com.noname.jar.core.AbstractFrontController.processRequest(AbstractFrontController.java:168)
    at сom.noname.jar.core/com.noname.jar.core.AbstractFrontController.doGet(AbstractFrontController.java:236)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at [email protected]/org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:542)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at [email protected]/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at [email protected]/org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
    at [email protected]/org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at [email protected]/org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at [email protected]/org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at [email protected]/org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at [email protected]/org.eclipse.jetty.server.Server.handle(Server.java:503)
    at [email protected]/org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at [email protected]/org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at [email protected]/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at [email protected]/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at [email protected]/org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at [email protected]/org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.base/java.lang.Thread.run(Thread.java:834)

At the same time methods protected Class<?> foundClass(final String name, URL url) and protected Class<?> findClass​(java.lang.String name) of my ClassLoader (extends WebAppClassLoader) which I set via webapp.setClassLoader are not used. Could you say how to explain it? (I use the newest jetty jpms code).

@sbordet About schemas

Note,
INFO org.eclipse.jetty.server.Server - jetty-9.4.z-SNAPSHOT; built: 2018-10-10T15:07:33.377Z; git: bd3eeeaa3f123e4c559e80ce21b5ab0ecbfb2f9c; jvm 11+28

2018-10-10 20:23:03:876 [RMI TCP Connection(2)-127.0.0.1] INFO org.eclipse.jetty.server.Server - jetty-9.4.z-SNAPSHOT; built: 2018-10-10T15:07:33.377Z; git: bd3eeeaa3f123e4c559e80ce21b5ab0ecbfb2f9c; jvm 11+28
2018-10-10 20:23:04:371 [RMI TCP Connection(2)-127.0.0.1] INFO org.eclipse.jetty.annotations.AnnotationConfiguration - Scanning elapsed time=58ms
2018-10-10 20:23:04:442 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [XMLSchema.dtd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:442 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [datatypes.dtd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:442 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [xml.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:443 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-app_2_2.dtd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:443 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-app_2_3.dtd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:444 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [j2ee_web_services_1_1.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:444 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [j2ee_web_services_client_1_1.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:444 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-app_2_4.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:444 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [j2ee_1_4.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:445 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-app_2_5.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:445 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_5.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:446 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_web_services_1_2.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:446 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_web_services_client_1_2.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:446 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-app_3_0.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:446 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-fragment_3_0.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:447 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-common_3_0.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:447 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_6.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:448 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_web_services_1_3.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:448 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_web_services_client_1_3.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:448 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-app_3_1.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:448 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-fragment_3_1.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:449 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [web-common_3_1.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:449 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_7.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:449 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_web_services_1_4.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.
2018-10-10 20:23:04:449 [RMI TCP Connection(2)-127.0.0.1] WARN org.apache.tomcat.util.descriptor.DigesterFactory - The XML schema [javaee_web_services_client_1_4.xsd] could not be found. This is very likely to break XML validation if XML validation is enabled.

Maybe I don't use some module? These are my modules:

    <module file="jetty-servlet-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-servlets-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-util-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-webapp-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-xml-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-http-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-io-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-security-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-server-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-annotations-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-jndi-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-plus-9.4.13-SNAPSHOT.jar"/>
    <module file="jetty-schemas-3.1.jar"/>
    <module file="org.eclipse.jetty.apache-jsp-9.4.13-SNAPSHOT.jar"/>
    <module file="javax.servlet-api-4.0.1.jar"/>
    <module file="asm-6.2.jar"/>
    <module file="asm-analysis-6.2.jar"/>
    <module file="asm-commons-6.2.jar"/>
    <module file="asm-tree-6.2.jar"/>
    <module file="classgraph-4.2.2-SNAPSHOT.jar"/>
    <module file="javax.annotation-api-1.2.jar"/>
    <module file="org.eclipse.jdt.ecj-3.12.3.jar"/>
    <module file="org.mortbay.jasper.apache-el-8.5.24.2.jar"/>
    <module file="apache-jsp-8.5.24.2.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-impl-1.2.5.jar"/>
    <module file="org.apache.taglibs.taglibs-standard-spec-1.2.5.jar"/>

See the difference before META-INF

@PashaTurok Yes, getURL() used to put "!/" between the jar name and the path within the jar, but now it just puts "!", because I noticed somewhere in the Java standard API omitted the leading slash in the path. What are you passing this URL to, and how does it complain when the slash is missing?

@lukehutch When I use your variant I get:

java.net.MalformedURLException: no !/ in spec
    at java.base/java.net.URL.<init>(URL.java:661)
    at java.base/java.net.URL.<init>(URL.java:523)
    at java.base/java.net.URL.<init>(URL.java:470)
        ....
Caused by: java.lang.NullPointerException: no !/ in spec
    at java.base/sun.net.www.protocol.jar.Handler.parseAbsoluteSpec(Handler.java:168)
    at java.base/sun.net.www.protocol.jar.Handler.parseURL(Handler.java:150)
    at java.base/java.net.URL.<init>(URL.java:656)
    ... 25 more

@PashaTurok interesting -- these URLs work fine without the "jar:" scheme prefix, which is why I didn't run into this before. The exception is only reported with that scheme prefix. Fixed in 4.2.11.

2934 has been merged into mainline jetty-9.4.x.

@sbordet Could you say if you answer two my last questions? Or I should ask them somewhere else? I mean about tag class loading and schemas. Note - I am using code from jetty-9.4.x master and get the same results as I described above.

@PashaTurok jetty-9.4.x has support for modules if you use it standalone.

For embedded usage, like you are doing, you have to do a lot of manual stuff yourself.

For the schemas, you have to patch the javax.servlet jar with jetty-schemas jar, see https://github.com/eclipse/jetty.project/blob/jetty-9.4.x/jetty-server/src/main/config/modules/server.mod.

For the TLDs, we already discussed this and it's all about letting Jetty scan classes at startup.
I thought you resolved this with ClassGraph.
We do the scanning here.

Now, you have a totally different setup, you use ModuleLayer, so I cannot help you with your code - only tell you what we have done in Jetty.

@sbordet Thank you very much for your help. Only two moments : 1) how to explain this patch-module: servlet.api=lib/jetty-schemas-3.1.jar in terms of java and JPMS but not Jetty? 2) I totally don't agree with you that Jetty must not support ModuleLayer. And the explanation is very simple - Layers are part of JPMS specs. If we say about Jetty JPMS support we must say also about layers support. But if Jetty JPMS support == Jetty JPMS modularization (within boot layer) then layers of course are not the issue.

Maybe I should open issue JPMS ModuleLayer support :)?

patch-module is a JPMS concept.

@PashaTurok you have stated multiple times what you think, and we understand it. You have already opened an issue about deploying a web application as a module layer, and we cannot do it in 9.4.x. Will be done in 10.x. There we will decide if it is also convenient that the server is in a module layer.
We also need to coordinate with the JakartaEE effort.

Was this page helpful?
0 / 5 - 0 ratings