0

I'm aware of similar questions here and here. And yet IMHO the issue is not yet fully covered, or at least it's still not working smoothly for me :(

What is the need:

I'd like to build a JAR packaged library, that will be used like a shared component in several WebApps, bringing within it the server logic as well as the relevant UI (web-components). Think of a UserService providing servlet/resource for login and signup calls from the server side perspective, while having UI components for end-to-end solution for any WebApp in the whole eco system from the client side.

So far:

Seems like this requirement exactly is addressed by a feature in Servlet 3.0 spec dealing with servlet web resources found in JARs under the path META-INF/resources.

I, seemingly, did exactly as it said, structuring the ui-components.jar having META-INF/resources/ui-commons/... under the root and configuring the following in the web.xml:

<servlet>
    <servlet-name>ui-commons</servlet-name>
    <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
    <init-param>
        <param-name>relativeResourceBase</param-name>
        <param-value>/WEB-INF/lib/ui-components.jar!META-NF/resources</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>ui-commons</servlet-name>
    <url-pattern>/ui-commons/*</url-pattern>
</servlet-mapping>

This definition comes before the default servlet definition serving the rest of the regular WebApp resources found in WAR as usual.

And yet, any request for the resources in that JAR ends up with 404.

Servlet version is 3.1.

Jetty 9.4.

It is NOT embedded Jetty, nothing fancy, but please pay attention to the notice below regarding the maven plugin.

Notice:

It might somehow be related to the fact that I'm currently trying to run this whole setup with jetty-maven-plugin, which is serving resources from the sources.

  • I've tried to drop the said JAR into the src/main/resources/WEB-INF/lib... manually - no success
GullerYA
  • 1,320
  • 14
  • 27

2 Answers2

1

Skip the <servlet> entries entirely.

Make sure your <web-app> descriptor is set to Servlet 3.0 or newer.

Example (for Servlet 3.1)

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
</web-app>

You MUST allow the war files to expand / extract. (this is set to true by default. If you are declaring it false in your context deployable ${jetty.base}/webapps/<name>.xml, or DeploymentManager configuration, or WebAppProvider configuration, then turn it back to true)

Makes sure you are using Jetty 9.2 or newer.

There's an example project demonstrating the META-INF/resources behavior and the jetty-maven-plugin at ...

https://github.com/jetty-project/jetty-example-metainf-resources

That's it, it's supported by default. No extra work required. (unless you are doing things on your own with embedded-jetty)

If using embedded-jetty, know that this will only work with a WebAppContext, not a ServletContextHandler.

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
  • Updated the Q with servlet and Jetty versions, all correct. What do you mean skip `servlet` entires? First, I do need the default servlet to serve other statics. And... how Jetty will find the correct JAR to pick resources from? And relative path? – GullerYA May 02 '19 at 14:46
  • skip, as in don't use, as in remove from your `web.xml`. `DefaultServlet` is provided to all webapps via the defaults descriptor, there's no need to manually declare it when using a `WebAppContext`. – Joakim Erdfelt May 02 '19 at 14:49
  • If I'd like to tune `DefaultServlet` behavior, like cache control, etags, not allowing directories listing etc, `` entry is the way to do that right (assuming no Java code involved)? – GullerYA May 04 '19 at 16:41
0

Okay, I've missed something and Joakim's answer pointed me to the right direction to find it.

In order to get resources from JARs to be served by Jetty, they first and foremost should be scanned by Jetty server.

By default, all the JARs in webapp's WEB-INF/lib are scanned. Yet, it is advised to fine tune this behavior and filter out all of the non relevant JARs to speed up the start time as per Jetty's documentation here.

So, first - be sure to review your WebInfIncludeJarPattern attribute configuration in WebAppContext setup and include the JAR that contains an additional static resources.

The rest of the setup for a 'foreign' JAR's resources (again, as Joakim pointed out) is identical to the regular webapp's resources, no need for any special path into the JAR as I've wrongly tried to do in my initial setup.

GullerYA
  • 1,320
  • 14
  • 27