I want to use a different source directory for a specific maven profile, however, when I try to specify it in the profile definition I get this error:
Unrecognised tag: 'sourceDirectory' (position: START_TAG seen ...<build>\r\n\t\t\t\t<sourceDirectory>... )
The definition in the pom is as follows:
<profile>
<id>development</id>
<build>
<sourceDirectory>${project.build.directory}/new-src</sourceDirectory>
.
.
.
</build>
</profile>
What I am trying to do is to process the source files before its compilation if and only if this profile is active. My process will change the source files on the fly, throw the changed sources in the "new-src" directory and compile that directory as if it was the usual "src/main/java". Everything else in the lifecycle should behave normally. If this approach is flawed, could anyone point me into the right direction?
According to the documentation, you can change only few <build> parameters in the profile and <sourceDirectory> is not one of them.
I'd configure the main <build> to take sources from path defined by some property (eg. src.dir), set this property to src/main/java and override it in the custom profile:
<project>
...
<properties>
<src.dir>src/main/java</src.dir>
</properties>
<build>
<sourceDirectory>${src.dir}</sourceDirectory>
...
</build>
<profiles>
<profile>
<id>development</id>
<properties>
<src.dir>${project.build.directory}/new-src</src.dir>
</properties>
</profile>
</profiles>
</project>
See Maven model, it is not allowed to define a sourceDirectory within a profile. The only thing you can do is specify the sourceDirectory within the plugin configuration, assuming it is available.
Related
We have a Maven 2 project with lots of modules in it. Example:
<modules>
<module>common</module>
<module>foo</module>
<module>data</module>
<module>bar</module>
... more ...
</module>
Let's say the "data" module is time consuming to build and we want to exclude it when the project is build by a CI server. Currently we use two pom.xml files to achieve this. One has all modules in it and the other one has all modules except the ones which can be left out for CI. But that's pretty annoying because sometimes we forget to put a new module into both files.
Is there a solution which doesn't need two separate module lists?
With Maven 3.2.1, you can now use -pl !<module_name>,!<module_name> to exclude certain modules from the reactor build.
See this feature request: https://issues.apache.org/jira/browse/MNG-5230
The easiest might be to use profiles like this:
<project>
...
<modules>
<module>common</module>
<module>foo</module>
<module>bar</module>
<modules>
...
<profiles>
<profile>
<id>expensive-modules-to-build</id>
<modules>
<module>data</module>
</modules>
</profile>
</profiles>
</project>
You should then check out ways you can activate profiles
The projects to build can also be specified on the mvn command line. This would remove the need for a separate pom, but instead you would have to change the CI configuration everytime there is a new module.
-pl,--projects <arg> Comma-delimited list of specified
reactor projects to build instead
of all projects. A project can be
specified by [groupId]:artifactId
or by its relative path.
Maybe a combination of this flag and --also-make-dependents or --also-make would reduce this maintenance burden again.
-am,--also-make If project list is specified, also
build projects required by the
list
-amd,--also-make-dependents If project list is specified, also
build projects that depend on
projects on the list
I assume you want the default build to always build everything, regardless of speed, so that new developers can get started quickly without having to understand lots about the POM. You can use profiles like this:
<modules>
<module>common</module>
<module>foo</module>
<module>bar</module>
</modules>
...
<profiles>
<profile>
<id>expensive-modules-to-build</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>data</module>
</modules>
</profile>
</profiles>
</project>
The problem with this is that if a developer specifies another profile on the command line, then the expensive-modules-to-build isn't included (unless the developer also specifies it). This makes it complicated to remember which profiles need to be included.
Here is a hacky way around that. Both profiles are always included, because the pom.xml file always exists. So to exclude the expensive modules, you can use -P!full-build on the command line.
<profiles>
<profile>
<id>full-build</id>
<activation>
<file>
<exists>pom.xml</exists>
</file>
</activation>
<modules>
<module>data</module>
</modules>
</profile>
<profile>
<id>short-build</id>
<activation>
<file>
<exists>pom.xml</exists>
</file>
</activation>
<modules>
<module>common</module>
<module>foo</module>
<module>bar</module>
</modules>
</profile>
</profiles>
Another idea: Reactor modules can be nested, so it should be possible to group your fast and slow-building modules into separate poms and then add another aggregator pom containing these two as modules. Your CI Server could then only reference the pom containing the fast building modules.
<artifactId>fast</artifactId>
<modules>
<module>fast-a</module>
<module>fast-b</module>
<module>fast-c</module>
</module>
<artifactId>all</artifactId>
<modules>
<module>fast</module>
<module>slow</module>
</module>
You could be to use maven profiles. In our build environment, we created a profile quick that disables many plugins and test execution.
This is done by
<profile>
<id>quick</id>
<properties>
<skipTests>true</skipTests>
<!-- others... -->
</properties>
<build>
<plugins>
<!-- configuration... -->
</plugins>
</build>
</profile>
And then we invoke maven the following way
mvn groupId:artifactId:goal -P quick
You could maybe disable compilation and other standard plugins in the pom of your module to speed it up.
Not exactly the answer these folks were asking for. My situation was I wanted to deploy only the parent pom. I'm using the spring-boot-thin-layout in a child module. This requires the parent module be deployed into artifactory. I added the following into my project. It enables skipping of install and/or deploy phase.
In my parent pom:
<properties>
<disable.install>true</disable.install>
<disable.deploy>true</disable.deploy>
<enable.deployAtEnd>true</enable.deployAtEnd>
</properties>
<profiles>
<profile>
<id>deploy-parent</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<disable.install>true</disable.install>
<disable.deploy>true</disable.deploy>
<deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>
<build>
<finalName>${project.version}</finalName>
</build>
</profile>
</profiles>
And the in my child pom(s) or any module you don't want deployed with parent:
<properties>
<maven.install.skip>${disable.install}</maven.install.skip>
<maven.deploy.skip>${disable.deploy}</maven.deploy.skip>
<deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>
So effectively when I run mvn deploy on the parent pom, it will compile all the modules, not run install on anything, and then at the end deploy any module not having <maven.deploy.skip>${disable.deploy}</maven.deploy.skip> in it's properties. So in my case only deploying the parent.
I have a project which I compile with maven. I have different profiles declared in pom.xml.
For some of these profiles, I prefer building a war, and for other profiles I prefer a jar. I use to manually edit the pom.xml file and change packaging variable to either
<packaging>war</packaging>
or
<packaging>jar</packaging>
before doing a
$ mvn clean package -Pchosenprofile
How can I tell mvn the packaging corresponding to each profile so I don't need to edit pom.xml?
If you want to use profile you can use something like:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
..
<packaging>${packaging.type}</packaging>
<profiles>
<profile>
<id>webapp</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<packaging.type>war</packaging.type>
</properties>
</profile>
<profile>
<id>batch</id>
<properties>
<packaging.type>jar</packaging.type>
</properties>
</profile>
</profiles>
</project>
Have you looked at the attachClasses configuration setting of the war plugin? This simple setting would let you build both a war and a jar (by default with the classifier "classes") in a single maven execution.
I don't think you can.
Two alternatives I can think of:
have two separate modules for packaging, and call one of those depending on profile
have your module in war and tweak the lifecycle (include/exclude build steps) depending on profile to produce your jar or your war
I like the second approach better - a build server would probably build both, and a developer would use the proper profiles/settings to skip the unwanted type.
If I add the following property in my POM, the maven-war-plugin uses it correctly:
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
However if I add the following property the plugin ignores it (the generated WAR has the default name, i.e. artifactId-version):
<properties>
<war.warName>${project.artifactId}</war.warName>
</properties>
Here are two excerpts from the maven-war-plugin documentation:
warName:
The name of the generated WAR.
Type: java.lang.String
Required: Yes
User Property: war.warName
Default: ${project.build.finalName}
failOnMissingWebXml:
Whether or not to fail the build if the web.xml file is missing. Set to false if you want you WAR built without a web.xml file. This may be useful if you are building an overlay that has no web.xml file.
Type: boolean
Since: 2.1-alpha-2
Required: No
User Property: failOnMissingWebXml
Default: true
(Source: https://maven.apache.org/plugins/maven-war-plugin/war-mojo.html)
Why is the behavior different between failOnMissingWebXml and war.warName?
Also, if other plugins can use the value ${project.build.sourceEncoding} why can't maven-war-plugin use the value of ${project.build.finalName}?
<properties>
<!-- plugins use these values correctly -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- not "found" by maven-war-plugin -->
<war.warName>${project.artifactId}</war.warName>
<project.build.finalName>${project.artifactId}</project.build.finalName>
</properties>
Thanks a lot! :)
EDIT: Since the version 2.4 of maven-war-plugin war.warName works as expected, however I still don't understand why setting project.build.finalName doesn't work.
The problem is simply that you mistaken property cause user property is meant to be used usually from command like this:
mvn -Dwar.warName=xxx war:war
If you like to use it in a pom file you have to use it like this:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warName>WhatEverYouLike</warName>
</configuration>
</plugin>
...
</plugins>
</build>
...
And you shouldn't use properties in your pom to define such things. Better use the configuration tag for this.
The ${project.build.finalName} should be used like this:
<project..>
<build>
<finalName>WhatYouLIke</finalName>
..
</build>
</project>
The structure can be seen if you look into the maven model.
The usage of ${project.build.sourceEncoding} is simply a convention in Maven plugins so you could define that property which is picked up by a larger number of plugins to be used for source encoding (I have to admit this is a little bit misleading). The original idea behind was having something in the maven model to represent the encoding which would mean to change it which is not really possible at the moment.
I have a maven project with multiple child projects. I also have a maven dbunit plugin which I invoke from command line like this:
mvn dbunit:operation -P test -pl .
-P is a profile switch where all necessary properties are stored (like db url, etc.)
I.e.:
<profile>
<id>test</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://localhost:5432/db</url>
<username>ers</username>
<password>ers</password>
<useQualifiedTableNames>true</useQualifiedTableNames>
<dataTypeFactoryName>org.dbunit.ext.postgresql.PostgresqlDataTypeFactory</dataTypeFactoryName>
<format>flat</format>
<type>INSERT</type>
<src>${basedir}/some_path/test.xml</src>
</properties>
</profile>
The problem I'm having is that I need to specify -pl . parameter to build only one project (root/parent project) so that the dbunit data is loaded only once. Is it possible to specify some property directly in the profile, so only 1 project is being build? I tried <pl>my_project</pl> and <project>... - but no luck. Thanks!
Yes. The <modules> element can be specified in a profile. So the solution would be to move the DBUnit setup code in a module and then:
<profile>
<id>test</id>
<modules>
<module>db-unit-setup<module>
</modules>
</profile>
If you activate this profile with -P test, only the single module db-unit-setup and the parent POM will be built. But since the parent POM is now an empty project (it's just a POM without any code), that shouldn't hurt.
As long as I run my project directly from Eclipse, I have no problem with that:
scene.getStylesheets().add(getClass().getResource("/stylesheet.css").toExternalForm());
But as soon as I run this code inside of a jar file, the resource is not found (NullPointerException).
I tried moving the css file to my src folder and then only stylesheet.cssas path instead of /stylesheet.css, but this leads to the same problem: Works fine using Eclipse, but not from the jar.
Hint: I am using Zonskis Maven JavaFX Plugin for generating the jar.
I just wasted my (your) time writing silly maven profiles.
instead of :
scene.getStylesheets().add(getClass().getResource("/stylesheet.css").toExternalForm());
simply write :
scene.getStylesheets().add("stylesheet.css");
This is how Zonski load css files.
Of course your stylesheet.css file should be in /src/main/resources, or somewhere on the CLASSPATH.
Move your file to src/main/resources and add your css file :
scene.getStylesheets().add(getClass().getClassLoader().getResource("stylesheet.css").toExternalForm());
Well, if you want to run it from the jar, then change stylesheet.css to stylesheet.bss ( binary css), package your application :
mvn clean compile jfx:build-jar
and run your jar.
java -jar app.jar
I have a ugly hack to make this a little usable (I'm using Netbeans,amazing maven integrity):
I create a project.properties file in src/main/resources directory,
file_css= ${file_css} // by default I use *.css file.
And make it filterable, in my POM file:
...
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version> 1.5 </version>
<configuration>
....
</configuration>
</plugin>
</plugins>
</build>
...
And create two maven profiles, one for dev, and the other for production (packaging to jar):
<profiles>
<profile>
<id>production</id>
<properties>
<file_css>stylesheet.bss</file_css>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<file_css>stylesheet.css</file_css>
</properties>
</profile>
</profiles>
So, you load your css file like this :
scene.getStylesheets().add(getClass().getClassLoader().getResource(ResourceBundle.getBundle("project").getString("file_css")).toExternalForm());
I use production profile for packaging, and dev for usual actions like compile, test, run.
Edit:
a complete example is hosted on github.