Maven Multiproject Profile activation via property - maven

I have a problem to activate a profile. There is a master pom with the profile:
<profile>
<id>EntityUpdater</id>
<activation>
<property>
<name>entityupdater.start</name>
<value>true</value>
</property>
</activation>
....
In my childpom (jar package) I specify the property:
<properties>
<!-- ENTITY UPDATER CONFIG -->
<entityupdater.start>true</entityupdater.start>
....
But in the build process the profile does not start.
I would be very happy if anyone could help me.
Best regards, Daniel

Unfortunately, Maven can only trigger property based profiles, if you are passing them in from the command-line as JVM args:
mvn clean package -Dentityupdater.start

Related

Setting Spring applicationContext properties from POM file

I have the following configurations in my applicationContext.xml file:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
<value>classpath:database.properties</value>
</list>
</property>
</bean>
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${smtp.host}" />
</bean>
with smtp.host being set in my POM file like so:
<build>
<defaultGoal>install</defaultGoal>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<application.env>local</application.env>
<profile.scope>compile</profile.scope>
<skip.test>true</skip.test>
<smtp.host>my.smtp.server</smtp.host>
</properties>
</profile>
Upon deploying my application, I ran into an error message saying that Spring was not able to resolve smtp.host. I added the following mapping to my application.properties file:
smtp.host=${smtp.host}
But Spring started to complain that I had a circular placeholder reference on the property. Is there anything I am missing?
Thanks!
You mix here two things up. The pom.xml is for building the application. Properties you define there has normally nothing to do with your application properties. And Maven profiles has nothing to do with Spring profiles. They are only named equaly.
You should configure your Spring Application as you can read here. You could -- what I would not suggest -- use your pom as property source.
The normal way would be to read it from a externalized configuration. As I do not know if you use Spring Boot, you can have a look at the Spring Boot Way and adapt it, if you use Spring without Boot.
So add a apllication.properties file into src/mein/resources like
smtp.host=my.smtp.server
If you use boot, you are done, else you have to add a
#PropertySource("classpath:/application.properties")
to your #Configuration
Here you are mixing the build and runtime phase of application which are mutually exclusive.
Mavens' role end once the build is complete thus any properties used perishes with it. Moreover application start up is agnostic to the tool / process used to build it and thus there isn't any information shared between them. Thus the idea to use properties specified in pom.xml is not feasible.
Regarding the circular reference the statement smtp.host=${smtp.host} is loosely similar to java code int i = i; which essentially has no effect because i is defined and assigned to itself.

How to negate a property in pom.xml?

I'd like to negate a boolean property as defined in pom.xml.
Meaning, given a property ${doSomething} I need to pass <skip> to a plugin where the value of <skip> should be the negation of ${doSomething}.
If ${doSomething} is false, then I want to skip. If it is true, then I don't want to skip. Any ideas?
Clarification: I am not talking about using the negation of a property for profile activation. I just want to pass the negation of a boolean into a plugin.
Apart from profile activation, Maven doesn't have a boolean logic implemented. So if want to negate a property to pass it to a plugin, you'll need to do it yourself. It is a bit clumsy, but you could use the build-helper-maven-plugin:bsh-property goal, which enables to write a BeanShell script and export variables defined in it as Maven properties:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.12</version>
<executions>
<execution>
<id>negate-prop</id>
<phase>initialize</phase>
<goals>
<goal>bsh-property</goal>
</goals>
<configuration>
<source>dontDoSomething = !${doSomething};</source>
<properties>
<property>dontDoSomething</property>
</properties>
</configuration>
</execution>
</executions>
</plugin>
You can't override the property, but you can define a new one containing the result of the negation; in the example above, it is dontDoSomething. This is ran in the initialize phase so that the rest of the plugins can use it as a parameter, with the standard ${dontDoSomething}.
This could be enhanced to have a default value for dontDoSomething if doSomething doesn't exist.
<source>
value = project.getProperties().getProperty("doSomething");
dontDoSomething = value == null ? false : !Boolean.parseBoolean(value);
</source>
BeanShell is a scripting language that looks very much like Java and you can use existing Java methods. In the above, the property "doSomething" is retrieved from the project's properties (project is injected by the plugin at evaluation-time with the current Maven project); it it isn't defined, we return false, otherwise, we negate the value.
If doSomething is specifically a system property, it could also be possible to (ab)use the profile activation feature and have 2 profiles: one activated by a property being true and setting another to false, and a second profile doing the inverse:
<profiles>
<profile>
<id>pro-1</id>
<activation>
<property>
<name>doSomething</name>
<value>!false</value>
</property>
</activation>
<properties>
<dontDoSomething>false</dontDoSomething>
</properties>
</profile>
<profile>
<id>pro-2</id>
<activation>
<property>
<name>doSomething</name>
<value>false</value>
</property>
</activation>
<properties>
<dontDoSomething>true</dontDoSomething>
</properties>
</profile>
</profiles>
This won't work if doSomething is a Maven property set in the <properties> tag for example. It will need to be passed as a system property with mvn -DdoSomething=true|false. The corresponding profile will be activated according to the value of the system property, which will define the dontDoSomething property to its inverse. If the property isn't defined, pro-1 will be active, setting dontDoSomething to the default value of false. All of this is quite ugly though...
I don't know the exact answer but I think you could try the following to invert the properties value (from http://maven.apache.org/guides/introduction/introduction-to-profiles.html). Declare another property where you invert the value of the first property:
<property>
<name>dontDoSomething</name>
<value>!${doSomething}</value>
</property>

CATALINA_HOME and Maven + LOG4J

I have this line in log4j:
log4j.appender.FILE.File=${catalina.home}/logs/debug.log
Works perfectly when I run the project from IntelliJ.
But when I try to run a TestNG test (from maven) it fails:
log4j:ERROR setFile(null,true) call failed.
java.io.FileNotFoundException: /logs/debug.log (No such file or directory)
I could hardcode the path and all will be good. But I don't want that solution since I can deploy on various systems where ${catalina.home} is in different place.
I develop on a mac and deploy on freebsd and centos. Tomcat is in different places all the time. I could use /var/log/myapp.log but ...
Is any way to define a common variable (available in IntelliJ and when I run the maven test) with the log file path?
Please try to use the Maven Profile which will be activated when the ${env.catalina.home} is not existed, together with the Maven Surefire Plugin:Using System Properties.
<profile>
<id>mock-catalina-home</id>
<activation>
<property>
<name>!env.catalina.home</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14</version>
<configuration>
<encoding>UTF-8</encoding>
<systemProperties>
<property>
<name>catalina.home</name>
<value>PATH_TO_CATALINA_HOME</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Please note that the PATH_TO_CATALINA_HOME can be referred by the Maven Properties as well. e.g.
<systemProperties>
<property>
<name>PATH_TO_CATALINA_HOME</name>
<value>${my.dev.catalina.home}</value>
</property>
</systemProperties>
This will help us to define the ${my.dev.catalina.home} to be various values.
I hope this may help.
In order for the log4j properties file get the correct value for ${catalina.home} when running the tests from maven, it needs to be in a file that is filtered by maven (src/main/resources is a directory for files like that). Also, the variable 'catalina.home' needs to be setup in maven. You can create a variable AKA maven property that uses an environment variable so you can define the different location for the tomcat install on each machine:
<properties>
<catalina.home>${env.catalina.home}</catalina.home>
<properties>
You can also specify the location of the log files in relation to the home directory for your user account.
In log4j this would use the following format: ${user.home}/weblogs/log4j1.log
In log4j 2, this would use the following format: ${sys:user.home}/weblogs/log4j2Rolling.log
log4j 2 can use the Java system properties, environmental variables, or Maven properties

Control Maven Reactor Modules with External Property File

My question is similar to this: How to exclude a module from a Maven reactor build?; however what I'd like to do is define a way of turning off-on modules based on a property. This property will be defined in an external property file we're using as our build profile.
The problem is that the property file isn't read in until the lifecycle after the Reactor is run (it appears Reactor is always run first).
Something like:
propertyfile.properties
module1.enabled = true
module2.enabled = false
module3.enabled = true
pom.xml
<profiles>
<profile>
<id>module1</id>
<activation>
<activeByDefault>false</activeByDefault>
<property>
<name>module</name>
<value>true</value>
</property>
</activation>
</profile>
...
</profiles>

Maven: include resource file based on profile

I'm converting an Ant webapp project over to Maven. I have most of it working, but I'm stuck trying to figure out how to copy some resource files from different sources based on the profile.
I have src/main/resources/persistence-{dev, prod}.xml. One of these needs to be included in the war file as WEB-INF/classes/META-INF/persistence.xml.
I would like the dev version to be copied when the dev profile is active, and the prod version when prod is active.
Just use the maven resources plugin like so http://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html and have a property for the file name or extension set in a profile.
If you are not wedded to the paradigm of having 3 separate persistence.xml files and copying one or the other selectively, you can use maven profiles with filtering like this (just implemented this the other day and today came across your post):
In persistence.xml:
<property name="hibernate.show_sql" value="${hibernate.debug}" />
<property name="hibernate.format_sql" value="${hibernate.debug}" />
In pom.xml create a profile and define the variable:
<profiles>
<profile>
<id>hib-debug</id>
<properties>
<hibernate.debug>true</hibernate.debug>
</properties>
</profile>
</profiles>
define a default for when you build without specifying a profile:
<properties>
<hibernate.debug>false</hibernate.debug>
</properties>
and.... make sure you turn on resource filtering:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
Then you build with mvn -Phib-debug and voila! Substitution is done.

Resources