How to filter resources when using maven jetty plugin?
Asked Answered
Q

4

8

I have an XML file (urlrewrite.xml) that needs a property placeholder resolved. I enable Maven filtering to achieve this. This works fine for the assembled WAR file.

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>

The problem is when trying to run the application in development mode using the maven-jetty-plugin (Maven Jetty Plugin), as maven jetty:run .

The file in question, urlrewrite.xml, is located in the src/main/resources directory, and therefore should (and does) ends up in /WEB-INF/classes (or target/classes for maven jetty:run).

The URLRewriteFilter config specifies the location of the config file as follows:

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    <init-param>
        <param-name>confPath</param-name>
        <param-value>/WEB-INF/classes/urlrewrite.xml</param-value>
    </init-param>
</filter>

This will work at deployment time. However, Using the jetty maven plugin, URLRewrite will die with a NullPointerException because it uses context.getResourceAsString("/WEB-INF/classes/urlrewrite.xml") in order to load the config file. Jetty returns null for this because when running the application from workspace it resolves /WEB-INF/classes/... to src/main/webapp/WEB-INF/... . The file does not exist there because the WAR has not yet been assembled. It should instead pull the resource from target/classes/urlrewrite.xml.

If that is obscure to you, then you probably won't be able to answer this question because I suspect you will need to be a Jetty guru to figure out a workaround (hint: that's a challenge!).

Does anyone know a way around this? I have also tried the following workarounds to know avail:

  1. Put urlrewrite.xml under a new directory, src/main/webResources and add it to the maven war plugin <webReources> and enable filtering. That will copy it's contents in the appropriate location when the WAR is packaged, but will not make it available for jetty:run
  2. Some other hacks I can't even remember ... (will update if I do)

In summary, maven-jetty-plugin needs the file to be under src/main/resources/webapp/insert path and filename in order to be available for the maven jetty:run command ...

Thanks for you help ...

Sincerely, Lloyd Force

Qualm answered 19/9, 2011 at 18:49 Comment(0)
Q
12

Answered my own question.

  1. Upgrade maven-jetty-plugin to at least 6.1.12

  2. See this wiki page on 'Configuring Multiple WebApp Source Directory' (available since jetty-6.1.12.rc2 and jetty-7.0.0pre3)

  3. Add some magic to pom.xml:

First, add a new directory (src/main/webResources) for your filtered web resources and add a <resource> element:

        <resource>
            <directory>src/main/webResources</directory>
            <filtering>true</filtering>
            <targetPath>../jettyFilteredResources</targetPath>
        </resource>

That will copy the files to target/jettyFilteredResources (we will reference this later). This directory will NOT get copied to your packaged WAR file, it is for jetty only!

Add the following element to your maven-war-plugin <configuration> element:

                <webResources>
                    <resource>
                        <directory>src/main/webResources</directory>
                        <filtering>true</filtering>
                    </resource>
                </webResources>

That will ensure everything is packaged up for your real WAR file.

Finally, tell jetty to use the resources your copied especially for it, by added the following snippet to your <baseResource> element:

<baseResource implementation="org.mortbay.resource.ResourceCollection">                        
    <resourcesAsCSV>src/main/webapp,target/jettyFilteredResources</resourcesAsCSV>
</baseResource>

Now everything will worketh! (Well, technically I haven't tested the production WAR yet, but ... blah ... it should work too).

If anyone has a better answer, I will accept it provided the answer is provided in a reasonable amount of time (say 1 day).

Qualm answered 19/9, 2011 at 19:23 Comment(3)
+1 For documenting solution (there are SO MANY unanswered questions on the net). If this works for you, do self-accept. Just an aside, have you tried to add 'Development' maven profile with specialized resource filtering? That was an approach I took for my non-jetty web project.Olivia
Optionally use the maven-replacer-plugin and have it write the replaced file out to the /WEB-INF/classes/ dir. It will make sure the dir structure exists.Gainsay
For those using Jetty 9: org.eclipse.jetty.util.resource.ResourceCollection instead of org.mortbay.resource.ResourceCollectionForcer
J
3

I think the answer in this other question is better:

Running resource filters when using jetty:run

Basically, instead of running 'mvn jetty:run' you have to use 'mvn jetty:run-exploded'.

The only drawback is that it needs to build the WAR file, which might be expensive in some cases. If that's not an issue for you, then I guess it's better.

Jocelin answered 10/9, 2012 at 21:38 Comment(1)
let me tell you, run-exploded is not an option; your talking about a few seconds versus several minutes; at least that was the case at the time that this post was written. the solution i posted above gives you the best of both worlds. yes, it's a hack. but it doesn't bleed into the actual application at all. it's just a build hack that you can forget about once it's set up. give it a shot and let me know what you think. i admit my answer was a bit terse as i was writing for the experienced maven user. i could update with more details if you think it would help.Qualm
B
2

add this to pom.xml:

    <resources>
        <resource>
            <directory>src/main/webapp/WEB-INF</directory>
            <filtering>true</filtering>
            <targetPath>../jettyFilteredResources</targetPath>
        </resource>
    </resources>

and this is how embedded Jetty server should look like:

        <plugin>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>9.1.3.v20140225</version>
            <configuration>
                <webAppConfig>
                    <descriptor>target/jettyFilteredResources/web.xml</descriptor>
                </webAppConfig>
                <scanIntervalSeconds>3</scanIntervalSeconds>
            </configuration>
        </plugin>

woila! thanks @les2 for inspiration ;-)

Blockage answered 8/7, 2014 at 9:30 Comment(1)
Did you have to implement this feature for the jetty-maven-plugin yourself? If so, that's awesome. It certainly makes the required configuration a lot simplier.Qualm
G
0

I found another way.

build the project and add the target folder as extra classpath.

<webAppConfig>
    ....
    <extraClasspath>${basedir}/target/mywebapp</extraClasspath>
    ....
</webAppConfig>
Gillyflower answered 2/10, 2014 at 13:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.