47

I have a Maven project that downloads some test files into its build directory ./target/files. These files should then be available to a servlet, which I can easily achieve by hardcoding the full path as an <init-param> of the servlet:

<servlet>
    <servlet-name>TestServlet</servlet-name>
    <servlet-class>my.package.TestServlet</servlet-class>
    <init-param>
        <param-name>filepath</param-name>
        <param-value>/home/user/testproject/target/files</param-value>
    </init-param>
</servlet>

How can I avoid hardcoding the full path and use a dynamic parameter replacement instead? I tried the following, but it did not work:

<param-value>${project.build.directory}/files</param-value>
dokaspar
  • 8,186
  • 14
  • 70
  • 98
  • Can you explain in more detail how your project downloads the test files? What triggers that? Normally problems like this are solved by enabling filtering, but it may be difficult depending upon how these files appear. – Duncan Jones Mar 12 '13 at 08:12

6 Answers6

90

Add to your pom section:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
        <webResources>
            <resource>
                <filtering>true</filtering>
                <directory>src/main/webapp</directory>
                <includes>
                    <include>**/web.xml</include>
                </includes>
            </resource>
        </webResources>
        <warSourceDirectory>src/main/webapp</warSourceDirectory>
        <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
    </configuration>
</plugin>

See Maven: Customize web.xml of web-app project for more details

Community
  • 1
  • 1
Andrzej Jozwik
  • 14,331
  • 3
  • 59
  • 68
  • 1
    See also https://maven.apache.org/plugins/maven-war-plugin/examples/adding-filtering-webresources.html for more info – tekumara Mar 12 '14 at 16:18
  • 5
    What's in the solution that enables the replacement? – AlikElzin-kilaka Jun 15 '16 at 07:52
  • @alikelzin-kilaka: you can define a property in your pom.xml (e.g. "Moin") and if you have in your web.xml a placeholder ("${myProp}") this will be replaced with the value of your property (with "Moin" in my sample) – Steffen Oct 21 '16 at 13:33
  • 1
    This one is actually replacing the placeholder with actual value from the pom property, but after deploying its giving error saying -- java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.profiles.to.active' in string value "${spring.profiles.to.active}". Whereas in .war and inside target folder its the new value. Any idea why its happening so? – John Maclein Dec 29 '16 at 19:37
  • @JohnMaclein I am having the same issue. It seems that all the found files are copied to the "warSourceDirectory". That means that the web.xml will be placed into the root folder. However: The tag is reading from the original WEB-INF folder where the property isn't replaced. Try "src/main/webapp/web.xml" – daPhantom Jan 11 '17 at 16:07
  • I believe that true is what does the trick of variable replacement – Jose Duarte Nov 03 '17 at 21:43
  • copy/paste, this solution worked perfectly. Now I was able to make a context param dependent on ${environment} – Skystrider Feb 01 '22 at 23:31
9

You can simply use maven filtering resources:

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

You can also combine this and would like to filter some files whereas others shouldn't be filtered:

   <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>false</filtering>
        <excludes>
          <exclude>**/*.xml</exclude>
        </excludes>
      </resource>
      ...
    </resources>

Put appropriate placeholders into the files you would like having replaced things like ${home}.

khmarbaise
  • 92,914
  • 28
  • 189
  • 235
  • This code does filters and replace strings in XML files with the values defined in the pom.xml tag or do I need to use a properties file? – madtyn Jul 06 '17 at 09:39
4

You can use Replace Ant Task to do it.

Heres a sample Implementation where i replace the tokenkeys in a property file , adapt it to suit your needs

test.properties

SERVER_NAME=@SERVER_NAME@
PROFILE_NAME=@PROFILE_NAME@

pom.xml

 <plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.7</version>
    <executions>
      <execution>
        <phase>compile</phase>
        <configuration>
          <tasks>

            <replace dir="${basedir}/src/main/resources" >
              <include name="**/*.properties"/>
             <replacefilter     token="@SERVER_NAME@" value="My Server"/>
             <replacefilter     token="@PROFILE_NAME@" value="My Profile"/>
            </replace>             

          </tasks>
        </configuration>
        <goals>
          <goal>run</goal>
        </goals>
      </execution>
    </executions>
  </plugin> 

voila! Now execute

mvn clean package
Sudhakar
  • 4,823
  • 2
  • 35
  • 42
  • 7
    Better use [resources filtering](http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html) instead of Ant. – khmarbaise Mar 12 '13 at 17:55
  • While the accepted answer is better for the actual question asked, this is actually exactly what I was looking for so I could replace versions for webjar dependencies in static html files. Thanks! – Pytry Nov 27 '15 at 04:07
4

I think you can use maven-war-plugin's filteringDeploymentDescriptors option to filter deployment descriptors -

<properties>
    <maven.war.filteringDeploymentDescriptors>true</maven.war.filteringDeploymentDescriptors>
</properties>
2

Add maven-war-plugin and set <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors> to replace the placeholder when running mvn package

<properties>
  <project.build.directory>your path</project.build.directory>
</properties>

<build>
  <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.2.2</version>
    <configuration>
      <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
    </configuration>
  </plugin>
</build>
xxg
  • 2,048
  • 1
  • 11
  • 14
1

Coding maven parameters in web.xml can't work directly, because at run time, when your application starts, maven has finished its work and the application has no knowledge about maven.

You can filter an alternative web.xml (see maven filtering: http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html) and use it when building the war (see the webXml parameter at the war plugin documentation: http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html)

Assen Kolov
  • 4,143
  • 2
  • 22
  • 32