Details
-
Type:
Improvement
-
Status:
Closed
-
Priority:
Major
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 2.0
-
Component/s: None
-
Labels:None
-
Number of attachments :5
Description
I'd like to patch the war plugin to perform resource filtering as per the resources plugin. This is a trivial patch but would duplicate the following code from the resources plugin:
PropertyUtils
ReflectionProperties
ResourcesMojo.copyFile(File, File)
These look like handy util methods that could be incorporated into plexus-utils - what do the developers think?
Also not sure how resource filtering will be affected by MNG-788.
-
- AbstractWarMojo.patch
- 01/Mar/06 1:19 PM
- 1 kB
- Scott Tavares
-
- MWAR-12.patch
- 21/Feb/06 1:35 AM
- 13 kB
- Brian Topping
-
- MWAR-12-maven-war-plugin.patch
- 28/Mar/06 8:34 PM
- 19 kB
- John Tolentino
-
- ResourcesMojo.patch
- 01/Mar/06 1:19 PM
- 0.8 kB
- Scott Tavares
-
Hide
- test.zip
- 01/Nov/05 8:48 AM
- 2 kB
- Mark Hobson
-
- test/pom.xml 0.6 kB
- test/src/main/filters/filter.properties 0.0 kB
- test/src/main/resources/resource.txt 0.0 kB
- test/src/main/webapp/webapp-resource.txt 0.0 kB
- test/src/main/webapp/WEB-INF/web.xml 0.0 kB
- test/src/.../filtered-webapp-resource.html 0.1 kB
Issue Links
- depends upon
-
MRESOURCES-5
Proposal for improved resource filtering
-
-
MRESOURCES-10
Filtering should handle java.io.File values
-
- is duplicated by
-
MWAR-14
Add the possibility to filter webapp files
-
- is related to
-
MNG-1683
type zip for packaging ?
-
Activity
I agree that we don't want to duplicate the filtering configuration. I don't like making it a general resource section where the user must specify the targetPath.
I think the best alternative might be to add some sort of "type" to the resource that the war plugin can use to select certain resource sets by.
Note also that kenney's idea is applicable to ear / rar plugins.
I noticed this isn't currently in the roadmap to be fixed. Is this a dead issue or something still to be pursued? I am very interested in the possibilities given the structure proposed by Kenney.
As a workaround to this issue, you can use a project structure like the one attached. It basically splits webapp resources off into filtered and unfiltered ones - leaving the war plugin to copy the unfiltered resources, and using the resources plugin to copy the filtered resources with a cunning "../finalName" path. This obviously relies on a standard maven project structure.
It also works if you want to profile-off your filters for different target environments.
Hi all,
Have a look to this http://jira.codehaus.org/browse/MNG-1683 (which a possible implementation of adding resources in the war plugin).
Hi,
Is it possible to imagine adding a phase called package-resources.
With this we could add some resources (same format as in the build section) in war configuration to include some stuffs which are not really mandatory for the compile :
- struts config files
- velocity templates
- ....
Note this phase could be used in others plugins which generates some files not really needed for compile (jar with manifest, ear with application.xml ..)
WDYT ?
- Olivier
I don't see that as being any different.
Really, I don't know that this should be called "resources". These are web resources that are different to normal classpath resources. It has been pointed out there are several cases of files being copied that should be filtered, utilising the resources plugin even if not the resources section of the POM.
related to http://jira.codehaus.org/browse/MWAR-22
I think that adding a prepare-package phase is the best way to go.
This will allow 2 things :
1) maven to provide a default way of filtering or selecting resources for the war
2) provides a way for custom mojos to hook in
Hi,
An other simple is using xdoclet-maven-plugin.
Actually I attached it tho the phase process-classes.
But when I just want to try a simple the simple : mvn -Dtest=something clean test.
All of my .java are parsed by the plugin whereas this should be done in a phase just before packaging.
I really need a phase just before package to place all this jobs
Olivier
I started working on a solution to this, not realizing that it was already in JIRA.
When I tried this a few weeks ago, my assumption was that I would add a <resources> block to the project POM. Since it already specified <packaging>war</packaging>, I just assumed that the same configuration would work here, but it doesn't.
Having gone through quite a bit of the code for both plugins by now, I can attest to the complexity of the resource filtering and how it would be good to avoid duplicating that into the war plugin. So I'm +1 for linking having these work together. It seems like a lot of the code in AbstractWarMojo.java could be removed if that were the case, and it looks like the class has had a lot of authors, so it would be worth doing.
Patch to resolve issue. POM must have plugin configuration such as:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0-beta-3-SNAPSHOT</version>
<configuration>
<filters>
<filter>$
</filters>
<resources>
<resource implementation="org.apache.maven.model.Resource">
<filtering>true</filtering>
<directory>${basedir}
/src/main/webapp</directory>
<includes>
<include>*/.properties</include>
<include>*/.xml</include>
<include>*/.vm</include>
</includes>
</resource>
<resource implementation="org.apache.maven.model.Resource">
<filtering>false</filtering>
<directory>$
/src/main/webapp</directory>
<includes>
<include>*/</include>
</includes>
<excludes>
<exclude>*/.properties</exclude>
<exclude>*/.xml</exclude>
<exclude>*/.vm</exclude>
</excludes>
</resource>
</resources>
</configuration>
</plugin>
I like the look of Brian's patch, but one thing I noticed when I attempted to use it is that there's a possible NullPointerException if the path to the filter file is incorrectly specified. Here's the diff to fix it:
— AbstractWarMojo.java.old 2006-02-24 09:39:23.000000000 -0700
+++ AbstractWarMojo.java 2006-02-24 09:46:13.000000000 -0700
@@ -409,10 +409,13 @@
for ( Iterator i = filters.iterator(); i.hasNext(); )
{ - String filtersfile = (String) i.next(); + String fname = (String) i.next(); + if (fname == null) throw new MojoExecutionException("Null filter file specified."); - Properties properties = PropertyUtils.loadProperties(new File(filtersfile)); + File filtersFile = new File(fname); + if (!filtersFile.exists()) throw new MojoExecutionException("Unable to find filters file " + fname); + Properties properties = PropertyUtils.loadProperties(filtersFile); filterProperties.putAll(properties); }}
Hi All,
I've been looking at this issue for some time now as well and have come up with a some what less complex solution, but it seems to work for me and may just as well for some of you.
Let me start by saying why this I need to have "add resource filtering to war plugin". Quite simply, I'm using JBoss and I need to change values in the WEB-INF\jboss-web.xml deployment file at build time. An example would be the <context-root> tag among others. So yes, there is reason to have resource filtering in this plugin... well kind of.
In order to understand my solution to this issue I think I need to explain the interaction that I belive actually happens between the war and resource plugins so that we are all on the same page.
The first behavior I noticed is where the two plugins write their output to. When the resource plugin writes out to the target folder, it does not respect the <finalName> tag in the POM like the war plugin does. I belive its default output folder is target/<project.artifactId> or something like that. On the other hand, the war plugin, when writing its output will first look for the <finalName> tag from the POM and if its there will use it and create a folder like this ~/>target/<finalName>. If it does not find a <finalName> tag in the POM it will then use something like ~/>target/<project.artifactId><project.version>. What this leads to is, most of the time there will be two sub-folders under the ~/>target/ directory (which leads into next issue, but more on that later). The exception to this is if the <finalName> tag and the <project.artifactId>-<project.version> tags where some how set to equal the same thing, then when each of the plugins write their output one will overwrite the other resulting in one sub-folder under the ~/>target directory.
The second issue/behavior I have already inherently stated. That is that war and resource plugins both do to a copy of the ~/>src/main/webapp directory to the ~/>target folder one after the other when you run the war plugin. Its the combination of these two behaviors that cause some nasty things to happen.
(DON'T TAKE THEASE EXAMPLES AS LITERAL)
Lets say that in the first example your POM is setup like this:
<project>
<artifactId>filtered-webapp</artifactId>
<build>
<finalName>webapp</finalName>
</build>
</project>
so that you will end up with a ~/>target folder like this:
/>target
filtered-webapp
webapp
and the problem is that the files from ~/>src/main/webapp will get filtered but the output from the resource plugin is in the />target/filtered-webapp folder, but when the war plugin builds the *.war file it is going use the files in the />target/webapp folder which have not been filtered!
For the second example lets say that the POM looks this:
<project>
<artifactId>filtered-webapp</artifactId>
<build>
<finalName>filtered-webapp</finalName>
</build>
</project>
so that you will end up with a ~/>target folder like this:
/>target
filtered-webapp
the main issue here is this. The resource plugin is going to read the ~/>src/main/webapp files and then filter them and write its output to the ~/>target/filtered-webapp folder. Then the war plugin is going to come along and grab a copy of the same ~/>src/main/webapp folder and write its output to the same ~/>target/filtered-webapp folder undoing the filtering the resource plugin just did. Then the war plugin will again use that same ~/>target/filtered-webapp folder to build the war file.
So as you can see in the current situation you can't win, either way you can not get filtered files into your webapp.
The solution I came up with does not add resource filtering to the war plugin just as someone else had suggested. It does not even add any new tags to the POM. It just tweaks the way these two plugins interact with each other. The funny thing about this whole thing is the solution I came up with is very simple. I patched the ResourcesMojo class so that it always writes its output the <finalName> tag from the POM just like the war plugin does. Then I patched the AbstractWarMojo class so that it first checks to see if there is an existing target/webapp folder before it create its own (so that it does not overwite one that the resource plugin may have put there) and copies the ~/>src/main/webapp to it.
I have been using this fix for a few weeks now and it seems to work just fine in all situations for me, but I'm sure some of you will most definitely find a fault in it somewhere. But I figured I share my experience and post the patches anyway, because the group may find some use of it. So here are the patch files...
Scott
Scott, IIUC your solution will only work for WARs, and will break resources for JARs.
We agreed on dev@maven.apache.org that classpath resources and webapp resources are different, which would be confused if the resources plugin were duplicated.
Brian's patch is closest to the correct solution (we can avoid the need for the implementation attribute), and the filtering/resource code needs to be in a library shared by the resources plugin and the war plugin (I'm not sure if this is the case in here or not).
I'll try and find some cycles to apply this.
May this issue be included in roadmap for 2.0 version?
I believe that many users waiting for this to be resolved (see also number of voters and watchers on this issue). Thank you.
Hi,
I'm trying to test Brian's patch out but I'm getting an error:
[INFO] Building Maven Webapp Archetype
[INFO] task-segment: [package]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] ----------------------------------------------------------------------------
[ERROR] FATAL ERROR
[INFO] ----------------------------------------------------------------------------
[INFO] org/codehaus/plexus/util/FileUtils$FilterWrapper
[INFO] ----------------------------------------------------------------------------
[INFO] Trace
java.lang.NoClassDefFoundError: org/codehaus/plexus/util/FileUtils$FilterWrapper
at org.apache.maven.plugin.resources.ResourcesMojo.copyFile(ResourcesMojo.java:217)
at org.apache.maven.plugin.resources.ResourcesMojo.copyResources(ResourcesMojo.java:174)
at org.apache.maven.plugin.resources.ResourcesMojo.execute(ResourcesMojo.java:91)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:432)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:530)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:472)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:451)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:303)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:270)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:139)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:322)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:115)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:249)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
At first I thought this may be from not having the dependency on plexus-utils set correctly but I confirmed that it is. Does any one have any suggections for me?
here is the POM of the maven-resources-plugin:
<project>
<parent>
<artifactId>maven-plugin-parent</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<version>2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>maven-resources-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>Maven Resources Plugin</name>
<version>2.2-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
and the POM for the test project i'm trying to build:
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Maven Webapp Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
<filters>
<filter>src/main/filters/database.properties</filter>
</filters>
<resources>
<resource implementation="org.apache.maven.model.Resource">
<filtering>true</filtering>
<directory>src/main/webapp</directory>
<includes>
<include>*/.properties</include>
<include>*/.xml</include>
<include>*/.vm</include>
</includes>
</resource>
<resource implementation="org.apache.maven.model.Resource">
<filtering>true</filtering>
<directory>src/main/webapp</directory>
<includes>
<include>*/</include>
</includes>
<excludes>
<exclude>*/.properties</exclude>
<exclude>*/.xml</exclude>
<exclude>*/.vm</exclude>
</excludes>
</resource>
</resources>
</build>
</project>
TIA
Scott
Hi, Scott,
I encountered this problem as well. I think that the issue is that mvn uses an older version of the resources plugin when it loads the POM, and for whatever reason the new resources plugin specified by the dependency in the war plugin doesn't override this. In essence, a bootstrapping problem.
It's been a few weeks since I looked at this, but I think I was able to resolve the issue by rebuilding the snapshot of the resources plugin, then setting up mvn to use that version instead. As I recall, however, doing this caused me problems elsewhere and I eventually abandoned the effort.
Sorry I couldn't be of more help,
Kris
Hi guys,
This patch requires that a recent version of plexus-utils-XXX.jar is on the classpath. Unfortunately, because plexus-utils is on the bootstrap classpath, it also needs to be replaced in the M2_HOME/core directory.
Once you get that, these errors should cease.
Let me know if that isn't sufficient.
Updated the patch submitted by Brian Topping to conform with current maven-war-plugin code and to successfully build with current version of maven (2.0.3). Attached patch has the filename MWAR-12-maven-war-plugin.patch.
If you use a $
{token} substitution in your path, the fix in 2.0.3 for this will still break. MRESOURCES-10 is the cause of that, since a java.lang.File is what the token evaluates to.
Hmm, I just installed plexus-utils-1.3-SNAPSHOT from svn, replaced my plexus-utils-1.1 in M2_HOME/core, added it as a dependency, configured the maven war plugin as per Brian Topping's message above, built maven-war-plugin 2.0-beta-3-SNAPSHOT from svn, added a build.properties file in src/main/webapp/WEB-INF/classes/build.properties and finally made a package, but no filtering happened in any xml files (no errors either).
Did I miss something? This is maven 2.0.4.
Thanks, J
What version of the war plugin is this issue "fixed" in? I'm using Maven version 2.0.6 - which uses maven-war-plugin version 2.0.2 - which still has in it's POM a dependency of plexus-utils version 1.0.4
I'm trying to use this feature, but I'm having problems. I've added a comment under MRESOURCES-8 where I think it belong better. See the comment here.
What I really like to see is the removal of warSourceDirectory. It should be just a resource directory,
specified in a <resource> section, with a different <targetPath> (the exploded war dir, not the WEB-INF/classes
dir or even the classes/ dir), or something like that. THe resources plugin should take care of copying it.
Here's a nice solution (I think):
Add a new mojo to the war plugin and bind it to a pre process-resources phase.
That mojo will take care of registering the (still existing) warSource directory as a resource root.
When process-resources is up, the resources plugin will pick that directory up and copy it, applying filtering.
The problem here is how to specify filtering - we don't want to do that in more than one place, if possible:
everything in MNG-788 would be duplicated for the configuration of this mojo then..
So we could specify the warSource directory as in a <resource> section too, where filtering can be specified.
It should somehow be marked as being the warSourceDirectory, for instance if the <directory> matches
the warSourceDirectory configuration (src/main/webapp). If there are no matches, the new mojo will
have created a resource section with default values.
If there exists one or more matching resource sections, a problem can be that targetPath is specified - what if it
doesn't match the temporary exploded webapp directory in target/ ?
If targetPath is not specified, the mojo will set the targetPath to the warSourceDirectory (for matching resource
sections!). normal resources go in target/classes, these should go in the exploded webapp root (not in WEB-INF/classes either).
Or there might be another, more general way to mark the resource for use of a specific plugin..