How to filter resources when using maven jetty plugin? - maven

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:
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
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

Answered my own question.
Upgrade maven-jetty-plugin to at least 6.1.12
See this wiki page on 'Configuring Multiple WebApp Source Directory' (available since jetty-6.1.12.rc2 and jetty-7.0.0pre3)
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).

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.

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 ;-)

I found another way.
build the project and add the target folder as extra classpath.
<webAppConfig>
....
<extraClasspath>${basedir}/target/mywebapp</extraClasspath>
....
</webAppConfig>

Related

Maven exclude resources not working as expected

I am trying to exclude from a build all YAML resource files, but the ones with a prod clause within the filename.
For example, given that my resource directory contains application-dev.yaml, application-test.yaml and application-prod.yaml, I would like application-dev.yaml and application-test.yaml to be excluded and application-prod.yaml to be kept.
The portion of my POM that deals with the resources is below:
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<excludes>
<exclude>**/*-!(prod).yaml</exclude>
</excludes>
</resource>
<resource>
<directory>${project.basedir}/web/WEB-INF</directory>
</resource>
</resources>
However, exclusion does not work and all YAML files are copied, including application-dev.yaml and application-test.yaml.
I tested the exclusion pattern in Bash shell by ls *-!(prod).yaml and it worked as expected.
At this point I am lost and am looking for the community assistance.
I thank you all in advance for your thoughts and comments.
In order to solve that I would go with maven profiles and resource plugin maven resource plugin
You can have variables to the resource file name according to what you need (prod, dev, etc)

Is It Possible to Set the user.agent Property from the Command Line Using the GWT-Maven-Plugin?

I know that in my *.gwt.xml file I can specify the browsers I want the GWT compiler to compile my app for by adding this to it:
<set-property name="user.agent" value="opera,ie8, gecko1_8, safari, ie9"/>
Is it possible for me to set this property on the command line when I build my project through maven? I'd like to be able to do something like this when I'm developing locally on my machine:
mvn clean install -Duser.agent="opera,ie8"
EDIT: Starting with GWT 2.7, you can now pass a -setProperty user.agent=… on the command line; no need to tweak gwt.xml files any more. I'm not sure Mojo Plugin for GWT let you use that though, but the net.ltgt.gwt.maven Maven Plugin for GWT can.
You can use filtering of your resources, but then it might make it harder to work from within your IDE.
In your gwt.xml:
<set-property name="user.agent" value="${user.agent}" />
Then in your pom.xml:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
and the default value for the property when you don't give it on the command-line:
<properties>
<user.agent>opera,ie8,gecko1_8,safari,ie9</user.agent>
</properties>
Note however that this goes against The Maven Way™.

How to access maven.build.timestamp for resource filtering

I am using maven 3.0.4 and would like to make the build timestamp accessible to my application. For this, I'm putting a placeholder in a .properties file and let maven filter on build. While this is working fine for ${project.version}, ${maven.build.timestamp} is not substituted on filtering.
The property seems to be available on build - I can use it to modify the artifact name:
<finalName>${project.artifactId}-${maven.build.timestamp}</finalName>
So why is it not available for resource filtering? And, more importantly, how do I make it accessible?
I have discovered this article, explaining that due to a bug in maven, the build timestamp does not get propagated to the filtering. The workaround is to wrap the timestamp in another property:
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
</properties>
Filtering then works as expected for
buildTimestamp=${timestamp}
I can confirm as of Maven 3.x {maven.build.timestamp} is "working" now. They work arounded the problem, apparently. No additional properties workaround needed anymore.
However, be careful your "filtering" plugin (maven-resources-plugin) is up to date. It needs to be relatively new, so if mvn help:effective-pom shows an old version (ex: 2.6), bump it to something newer, fixed it for me, 3.x ex:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<properties><timestamp>... workaround is no longer required...
This also cleared up, kind of, why it was working in IntelliJ but not the command line. IntelliJ probably uses their own "modified/internal" maven constants, so it was working there, but not from maven command line.
Also note if you add a filtering resource directory to you pom, you may need to also "re-add" the default directory, it gets lost, ex:
<resource>
<directory>src/main/resources-filtered</directory> <!-- to get "maven.build.timestamp" into resource properties file -->
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory> <!-- apparently have to add this is you have the other... -->
</resource>
NB if you're using spring boot as your parent, you have to use #maven.build.timestamp# instead. Also note if you're using spring boot there's a file META-INF/build-info.properties that is optionally created by the spring-boot-maven-plugin that you can read (spring provides a BuildProperties bean for convenience reading it).
In order to enrich the Stackoverflow content for others, that like me, found this post as a way to solve the "problem" of ${maven.build.timestamp}. This is not a maven bug, but an expected behavior of m2e, as can be seen in this post.
Therefore, I believe that we can not expect the solution to be "corrected", since, from what I understand, the correction involves conceptual issues.
In my case, what I did was use the plugin (buildnumber-maven-plugin) as described in this other post.
Adding Maven properties at the pom project level doesn't take into account correct local Timezone, so timestamp may appear wrong :
<properties><timestamp>${maven.build.timestamp}</timestamp></properties>
Using the build-helper-maven-plugin applies the correct timezone and current daylight saving to the timestamp :
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>timestamp-property</id>
<goals>
<goal>timestamp-property</goal>
</goals>
<configuration>
<name>timestamp</name>
<pattern>yyyy-MM-dd HH:mm:ss</pattern>
<timeZone>Europe/Zurich</timeZone>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
When packaging, Maven will replace any token timestamp in /resources folder, e.g. resources/version.properties :
build.timestamp=${timestamp}
You can then load this properties file in your Application.

Is there a way to remotely deploy EAR to Oracle AS using maven?

Is there a way to remotely deploy an EAR after building it to Oracle AS? Remote deployment functionality exists for Eclipse, and I'm looking for something similar for maven2:
http://download.oracle.com/docs/cd/E14545_01/help/oracle.eclipse.tools.weblogic.doc/html/conFeatureOverview.html#remoteDep
Verified on Oc4j 10
http://chadthedeveloper.blogspot.com/2008/05/automated-deployment-to-oc4j-in-maven2.html
Have you tried the Weblogic Maven plugin? The weblogic:deploy goal seems to do exactly what you want. I've not used it myself so can't confirm if it actually works or not.
Update:
Found this blog that describes deploying to 10.1.3, though not using the weblogic plugin.
This is not a complete answer your question; is's just a checklist for things to look up while solving this:
what to do with generated sources, when to generate them?
do you need custom information in META-INF?
how to manage jars?
you can have them installed in an external repository, local repository, or specify them with system, on a project relative path, or a system absolute path
if specified with system, you can keep compile time jars in any location, and those that you want inside wars inside webapp/WEB-INF
If your project has a maven friendly architecture, then ok. Otherwise you can specify custom paths like this:
<packaging>ear</packaging>
<build>
<finalName>ear-name</finalName>
<!-- you can have only one source path-->
<sourceDirectory>src-dir-path</sourceDirectory>
<!-- you can have only one test path-->
<testSourceDirectory>test-dir-path</testSourceDirectory>
<!-- you can have several resource paths -->
<resources>
<resource>
<directory>src-resources-path</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<!-- you can have several test resource paths -->
<testResources>
<testResource>
<directory>test-resources-path</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
</build>
Other tips:
study Eclipse generated ear, and maven generated ear, check for differences
you can find missing jars with mvn compile, don't use an IDE for this, you want to make sure that maven has all the jars it needs
you can have ant scripts inside maven, use maven-antrun-plugin, i can provide examples if requested

Where should I put application configuration files for a Maven project?

I'm using the Maven Application Assembler plugin to generate stand-alone executables from my Java project. The application reads in configuration files, including Spring files. The Application Assembler plugin has an option (activated by default) to add a etc/ directory to the application's classpath, but what should I do to have the plugin copy my configuration files to this directory?
Or more generally, where is in Maven the kosher location for application configuration files that should NOT be packaged in the artifact?
You can also use resource filtering:
http://maven.apache.org/guides/getting-started/index.html#How_do_I_filter_resource_files
turn on filtering:
...
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
...
make a file under src/main/resources like: application.properties
application.properties
configprop.1=${param1}
configprop.2=${param2}
Then setup a profile and set some properties perhaps in a settings.xml
that sets different properties depending on if this is a dev or production build.
see: http://maven.apache.org/guides/introduction/introduction-to-profiles.html
I have different properties set depending on if this is the build server, dev or a production deployment
mvn -Denv=dev || mvn -Denv=dev-build || mvn -Denv=production
The maven link has a pretty good description.
For folks who have come to this more recently there is, since version 1.1 of the Application Assembler Plugin, the optional parameters configurationSourceDirectory and copyConfigurationDirectory. Please find them in an example POM.xml extract below:
<configuration>
<!-- Set the target configuration directory to be used in the bin scripts -->
<configurationDirectory>conf</configurationDirectory>
<!-- Copy the contents from "/src/main/config" to the target
configuration directory in the assembled application -->
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<!-- Include the target configuration directory in the beginning of
the classpath declaration in the bin scripts -->
<includeConfigurationDirectoryInClasspath>
true
</includeConfigurationDirectoryInClasspath>
...
</configuration>
More information is here
You could try the maven assembly plugin. I used it in conjunction with the appassembler plugin.
Configure appassembler to point to whatever name you want for your configuration directory, if you don't want 'etc'. The assembly plugin assembles everything in its own output directory, so I configure the assembly plugin to copy the bin and repo dirs from the appassembler directory into its output dir, then I have it copy the config files (mine are in src/main/config) into the expected config dir. There is some duplication in this, because you are copying the appassembler outputs, but that didn't really bother me.
So what you have after executing the assembly plugin is your bin, repo, and config dir are all peer directories under the assembly output directory. You can configure it to have a different structure if you prefer, I just wanted mine to mirror the appassembler structure.
The nice thing is that you can also configure the assembly plugin to change your binaries to executables, which I could't see how to do with appassembler. And, if you then bind appassembler:assemble and assembly:single goals to the package phase, all you have to do is 'mvn package', and it assembles everything.
I don't know if I understand you correctly. But what I have done in the past for a project where I needed to copy configuration files, is use the Maven AntRun plugin. What I did is execute the plugin in the process-resources phase and copied my configuration files to the specified directory using the Ant copy task. The Assembler plugin executes in the package phase so it should pick up your configuration files if you put it in the right place. Hope this answers your question a little bit.
I had been looking for an answer to what I think is your question, or at least a very similar question. Maven allows you to specify directories for resources using the maven-resources-plugin. I have a few configuration files in one of my resource directories. I've noticed that by putting copies of those files in the etc/ directory that you mention (which is at the beginning of my CLASSPATH) I can change values in those files for use at run time. I then wanted to have that etc/ directory created with copies of everything from my resource directory by default. The copy-resources goal from the maven-resources-plugin allowed me to do that. This stanza from Examples > Copy Resources on the left sidebar (I'm limited to 2 links in this post) is what did it for me:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/extra-resources</outputDirectory>
<resources>
<resource>
<directory>src/non-packaged-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
...
</project>

Resources