jetty / jetty.project

Eclipse Jetty® - Web Container & Clients - supports HTTP/2, HTTP/1.1, HTTP/1.0, websocket, servlets, and more
https://eclipse.dev/jetty
Other
3.79k stars 1.91k forks source link

Define core deployment #11861

Open sbordet opened 1 month ago

sbordet commented 1 month ago

Jetty version(s) 12.0.x

Jetty Environment core

Description Currently, the deployment of a Jetty core web application not documented and cumbersome (but works).

To deploy a core webapp, one needs the following structure:

$JETTY_BASE/webapps
├── foo-webapp.xml
└── foo-webapp.d
       ├── classes
       │   └── org
       │       └── foo
       │           └── ServerApp.class
       └── lib
           ├── jetty-util-12.0.9.jar
           ├── ...
           └── slf4j-api-2.0.12.jar

where foo-webapp.xml is a Jetty context XML file, foo-webapp.d/classes contains the webapp classes, and foo-webapp.d/lib contains the webapp dependencies.

Creating this structure is currently not automated, and users must manually create it. Furthermore, it is not a single file like a *.war, so it's not particularly easy to copy around, atomically deploy it, etc. Users would also have troubles generating the lib directory with all the dependencies.

We should discuss if there are simpler options to allow users to deploy a Jetty core web application, possibly using a single file.

sbordet commented 1 month ago

One idea is to re-use the *.war format, with no WEB-INF/web.xml but a WEB-INF/jetty-web.xml.

We already support WEB-INF/jetty-web.xml for eeN deployments, so we should be able to reuse all the code.

This solution has the benefit that people can develop webapps using the IDE, the m-war-p, without having to resort to special build configurations (for example, using the m-dependency-p to figure out all the transitive dependencies that must go into lib).

It would also benefit of the fact that WEB-INF is protected from remote access, while it is not clear (or currently strongly defined) for foo-webapp.d.

gregw commented 1 month ago

The minimal requirements for deploying a core application is just a context.xml file. It is entirely plausible for such an app to take all it's classes from the containers classpath, maybe even only using utility handlers, or perhaps some application code dropped into $jetty.home/lib.
If fact your example is kind of wrong as you should not need to provide either jetty-util nor jslf4j-api jars to a core application. We do not hide any "server" jars from a core application.

I think we should look at an example of creating and deploying a core application with our module system, which already has the ability to move jars into lib, config into etc (or a .d) and to deploy an xml in webapps. I think one of the main advantages of a core application is that it blurs the line between container and application, so it could be thought of as a server component.

However, I agree that is not the only way that users might look at a core application and having a single file deployable is also a good idea. But I don't think we should try to invent our own single file deployment format... but I'm not opposed to reusing the war format (even if it is not very good for purpose). I'm not sure how much code reuse we can achieve, as a core app will be based on a ContextHandler not a WebAppContext, so it will not have the Configuration mechanism used to configure an EE webapp. That is not necessarily a bad thing, as the EE webapp deployment stuff is already insanely complex with programmatic, annotated, descriptor, convention based configuration from many generations of specification with a smear of CDI influence on top. Adding more conditions to that code is probably not a great idea - it needs to stay focused on meeting the spec. To rewrite some code that will use the contents of a core-war as the resourceBase and protect the WEB-INF subdirectory is not that difficult. We probably would want to extract some common code for unpacking (but again that is already so much more complex than you'd think).

sbordet commented 1 month ago

The minimal requirements for deploying a core application is just a context.xml file. It is entirely plausible for such an app to take all it's classes from the containers classpath, maybe even only using utility handlers, or perhaps some application code dropped into $jetty.home/lib.

Yes, but my point is that developers would rather have a clear path of what to do. The suggestion to use JETTY_HOME/lib kinda goes against our JETTY_BASE concept, so it works, but not ideal. Sure we can document to use the ext Jetty module, but that would be accessible to all webapps, which perhaps it's not ideal.

If fact your example is kind of wrong as you should not need to provide either jetty-util nor jslf4j-api jars to a core application. We do not hide any "server" jars from a core application.

Fair enough, mine was an example.

think one of the main advantages of a core application is that it blurs the line between container and application, so it could be thought of as a server component.

But there is also the case where I just want to deploy a better integrated Jetty webapp as if it was a normal webapp.

For example, CometD 8 has now a CometDHandler, so the deployment of such CometD webapp would be:

$JETTY_BASE/webapps
├── cometd.xml
└── cometd.d
       ├── classes
       │   └── org
       │       └── acme
       │           └── cometd
       │               └── MyCometDService.class
       └── lib
           ├── cometd-java-server-http-jetty-8.0.2.jar
           ├── ...
           └── jetty-util-ajax-12.0.10.jar

In particular:

I would say that for a non-trivial Jetty core webapp, we need <app>.d/classes and <app>.d/lib in almost all cases, plus app.xml.

With a *.war format it would be:

$JETTY_BASE/webapps
└── cometd.war
       ├── index.html
       ├── cometd.js
       └── WEB-INF
           ├── jetty-web.xml
           ├── classes
           │   └── org
           │       └── acme
           │           └── cometd
           │               └── MyCometDService.class
           └── lib
               ├── cometd-java-server-http-jetty-8.0.2.jar
               ├── ...
               └── jetty-util-ajax-12.0.10.jar

The root of the *.war would contain the CometD JavaScript files to serve to clients, as well as HTML, CSS, etc.

With this, we would not need the <app>.d (we may have it, but it would not be mandatory like it is now, as the *.war is self-contained), and reuse a well known deployment format that would be familiar to developers.

janbartel commented 1 month ago

One idea is to re-use the *.war format, with no WEB-INF/web.xml but a WEB-INF/jetty-web.xml.

We already support WEB-INF/jetty-web.xml for eeN deployments, so we should be able to reuse all the code. It would be a matter of copying the code up into jetty-core somewhere as reading of WEB-INF/jetty-web.xml is read by the JettyWebXmlConfiguration class, and Configuration classes are not part of jetty-core.

This solution has the benefit that people can develop webapps using the IDE, the m-war-p, without having to resort to special build configurations (for example, using the m-dependency-p to figure out all the transitive dependencies that must go into lib).

It would also benefit of the fact that WEB-INF is protected from remote access, while it is not clear (or currently strongly defined) for foo-webapp.d.

Again, IIRC WEB-INF is not protected in jetty-core, but by the eeX specific webapp modules.

I'm not sure I like reusing WEB-INF directory for this purpose. We could use META-INF instead as maven already supports putting stuff in there? In fact, the jetty-osgi code already has a series of extra headers defined for MANIFEST.MF that allows it to deploy a plain .jar file that contains classes, lib ,context.xml and static content. Maybe we could look at that type of solution?

sbordet commented 1 month ago

@janbartel it would be complicated to set up for users. Right now with the m-war-p everything is automatic with almost zero POM configuration.

Rebuiliding exactly the same structure under META-INF would be a lot more POM configuration with possible errors, etc. for exactly the same structure, but now you have to use also the m-dependency-p, the m-jar-p, etc.

olamy commented 1 month ago

if needed we can create our own maven packaging type (and plugin) to help users. so the user setup would be as simple as adding a line such

<packaging>jetty-core-or-whatever-name-we-prefer</packaging>
sbordet commented 1 month ago

if needed we can create our own maven packaging type (and plugin) to help users.

Sure, but my point is that we don't need to, as there already exist one that is widespread and supported by IDEs (ours won't be) and tools.

gregw commented 3 weeks ago

I'm not sure I like reusing WEB-INF directory for this purpose. We could use META-INF instead as maven already supports putting stuff in there? In fact, the jetty-osgi code already has a series of extra headers defined for MANIFEST.MF that allows it to deploy a plain .jar file that contains classes, lib ,context.xml and static content. Maybe we could look at that type of solution?

I think we should protect both WEB-INF and META-INF in a core single file deployment, not least because I can imagine a real war being accidentally deployed as core and we should not expose its web.xml and other WEB-INF content. I don't mind this as it is convention over configuration.

I also think that if OSGi has a single file format that we should look at supporting that as well... maybe even both at the same time.