How to read maven settings in .m2/settings.xml file from plugin - java

Three questions in decreasing order of importance - Links will do.
I need to read certain maven settings such as proxies, servers in my maven plugin. How do I read them from my plugin. I can read from .m2/settings.xml file but I think there must be an easier way (some API that already does it).
I see from developers cookbook there is a class org.apache.maven.project.MavenProject What dependency I need for this to be available in my plugin - I feel this would be good to have.
Is it possible to have my own properties in settings.xml say for example
<users> <user> <username>user_name1</username> <password>encrypted_password</password> </user></users>
How ?
PS: I am a beginner.
Update 1
I was able to create and read custom properties following Injecting POM Properties via Settings.xml. However I would like to have configuration similar to what cargo provides. E.g.
<servers>
<server>
<id>tomcat7_local</id>
<configuration>
<cargo.hostname>localhost</cargo.hostname>
<cargo.remote.uri>http://localhost:8080/manager/text</cargo.remote.uri>
<cargo.remote.username>my_username</cargo.remote.username>
<cargo.remote.password>my_password</cargo.remote.password>
<cargo.servlet.port>8080</cargo.servlet.port>
</configuration>
</server>
<server>
<id>tomcat6_local</id>
<configuration>
<cargo.hostname>localhost</cargo.hostname>
<cargo.remote.uri>http://localhost:8080/manager</cargo.remote.uri>
<cargo.remote.username>my_username</cargo.remote.username>
<cargo.remote.password>my_password</cargo.remote.password>
<cargo.servlet.port>8080</cargo.servlet.port>
</configuration>
</server>
</servers>
How do I achieve this. Have a kind of workaround for my 3rd problem not sure if its the right way.
Edit
Thanks Jordan002! I know I can have multiple profiles but I didn't know to use them. This way by having profiles I can set my variable's value or rather inject the value in my plugin by saying something like #Parameter(alias = "cargo.hostname")
private String hostname; But as I see, for cargo plugin all it requires is defined like below
<servers>
<server>
<id>someId</id>
<configuration>
<!-- Configurations are placed here -->
</configuration>
</servers>
Similarly, or may be not so similar as there is no configuration here
<proxies>
<proxy>
<active>true</active>
<protocol>http</protocol>
<host>My_proxy_host</host>
<port>My_proxy_port</port>
</proxy>
</proxies>
is where I can put proxy information that maven uses. Now, I don't want to redefine it inside some profiles and I don't want to parse this file to get informations.
Further, I would like do something like cargo is doing. It lets me write all the configuration inside servers and in project's pom I only have to do following
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<container>
<containerId>tomcat7x</containerId>
<type>remote</type>
</container>
<configuration>
<type>runtime</type>
<properties>
<cargo.server.settings>tomcat7_local</cargo.server.settings>
</properties>
</configuration>
<deployer>
<type>remote</type>
</deployer>
<deployables>
<deployable>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<type>war</type>
<properties>
<context>${project.artifactId}</context>
</properties>
</deployable>
</deployables>
</configuration>
</plugin>
And cargo picks up configurations(s) that I defined for tomcat7_local, no need to write a profile for this.

Inject the setttings component as described here http://maven.apache.org/plugin-tools/maven-plugin-tools-annotations/
Its in Maven core org.apache.maven:maven-core:3.0.5
use properties directly and not nested. e.g. http://maven.apache.org/examples/injecting-properties-via-settings.html

I'm not too familiar with the Cargo plugin, but from the documentation, it appears to be configurable as any other Maven plugin would be. What I would change from your 'Update 1' would be to make tomcat6 and tomcat7 profiles:
<profiles>
<profile>
<id>tomcat6_local</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<cargo.hostname>localhost</cargo.hostname>
<cargo.remote.uri>http://localhost:8080/manager/text</cargo.remote.uri>
<cargo.remote.username>my_username</cargo.remote.username>
<cargo.remote.password>my_password</cargo.remote.password>
<cargo.servlet.port>8080</cargo.servlet.port>
</properties>
</profile>
<profile>
<id>tomcat7_local</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<cargo.hostname>localhost</cargo.hostname>
<cargo.remote.uri>http://localhost:8080/manager</cargo.remote.uri>
<cargo.remote.username>my_username</cargo.remote.username>
<cargo.remote.password>my_password</cargo.remote.password>
<cargo.servlet.port>8080</cargo.servlet.port>
</properties>
</profile>
</profiles>
and indicate at run time which tomcat you would like to start/stop by passing in the appropriate profile:
mvn install -P tomcat6_local
Hope this helps.

Related

Setting default arguments for Maven [duplicate]

I have a Maven pom.xml with a plugin that I want to be able to control on the command line. Everything works otherwise fine, except even after searching the net a while I can't figure out how to set a default value for my control property:
<plugin>
...
<configuration>
<param>${myProperty}</param>
</configuration>
...
</plugin>
So if I run Maven with
mvn -DmyProperty=something ...
everything's fine, but I'd like to have a specific value assigned to myProperty also without the -DmyProperty=... switch. How can this be done?
You can have the property default value defined in <build>/<properties> or in a profile like shown below. When you supply the property value on command line with -DmyProperty=anotherValue then it will override the definition from the POM. That is, all definitions of property values in the POM are set only a default value for the properties.
<profile>
...
<properties>
<myProperty>defaultValue</myProperty>
</properties>
...
<configuration>
<param>${myProperty}</param>
</configuration>
...
</profile>
Taylor L's approach works fine, but you don't need the extra profile. You can just declare property values in the POM file.
<project>
...
<properties>
<!-- Sets the location that Apache Cargo will use to install containers when they are downloaded.
Executions of the plug-in should append the container name and version to this path.
E.g. apache-tomcat-5.5.20 -->
<cargo.container.install.dir>${user.home}/.m2/cargo/containers</cargo.container.install.dir>
</properties>
</project>
You can also set properties in your user settings.xml file in the event that you want each user to be able to set their own defaults. We use this approach to hide credentials that the CI server uses for some plug-ins from regular developers.
You could use something like below:
<profile>
<id>default</id>
<properties>
<env>default</env>
<myProperty>someValue</myProperty>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
#akostadinov's solution works great for common usage... But if the desired property shall be used by reactor component during dependency resolution phase (very early in mvn pom hierarchy processing...) you should use profile "none activation" test mechanism to ensure the optional command line provided value is always prioritized regarding the value provided inside pom.xml. And this whatever deep is your pom hierarchy.
To do so, add this kind of profile in your parent pom.xml :
<profiles>
<profile>
<id>my.property</id>
<activation>
<property>
<name>!my.property</name>
</property>
</activation>
<properties>
<my.property>${an.other.property} or a_static_value</my.property>
</properties>
</profile>
</profiles>
This might work for you:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugin>
<configuration>
<param>Foo</param>
</configuration>
</plugin>
</build>
...
</profile>
<profile>
<id>notdefault</id>
...
<build>
<plugin>
<configuration>
<param>${myProperty}</param>
</configuration>
</plugin>
</build>
...
</profile>
</profiles>
That way,
mvn clean will use "foo" as your default param. In cases when you need to override, use mvn -P notdefault -DmyProperty=something
I took sal's approach but flatten it a bit.
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugin>
<configuration>
<version>LATEST</version>
</configuration>
</plugin>
</build>
</profile>
</profiles>
Now you have 2 options:
Using default value: MVN install (all $version will be replaced with LATEST)
Using own value: MVN install -P! Default -Dversion=0.9 (all $version will be 0.9)

Maven compiler configuration via built-in properties?

The Maven Compiler Plugin compile goal indicates (as many of you already know) that I can turn off debug information by setting <debug>false</debug>.
<project …>
…
<profiles>
<profile>
<id>production</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<debug>false</debug>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
I note however that the same documentation indicates that the "user property" for this setting is maven.compiler.debug. What does it mean that something is a "user property"? Does this mean that I can simply set the maven.compiler.debug property to false in my profile, and not even mention anything about a plugin, like this?
<project …>
…
<profiles>
<profile>
<id>production</id>
<properties>
<maven.compiler.debug>false</maven.compiler.debug>
</properties>
</profile>
</profiles>
</project>
As answered in another question:
"User property" specifies the name of the Maven property that can be used to set a plugin parameter. This allows configuring a plugin from outside the section. Note that this only works if the parameter is not specified in the section (see MNG-4979 - Cannot override configuration parameter from command line).
The "User property" on Maven3 can be used on the command line, by specifying
-Dmaven.compiler.debug=false or
in a POM profile like example below, as per your question:
<properties>
<maven.compiler.debug>false</maven.compiler.debug>
</properties>

In maven, how to name war file different in release than in snapshot build

I'm using the maven-war plugin. I've also looked at the maven-versions plugin. In neither case do I see how to give a different name to a snapshot build than a release build.
I've seen examples using profiles but the docs seem to indicate that the use of profiles in the pom.xml is not a good idea.
How should this be done?
Try the below
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>src\main\webapp\WEB-INF\web.xml</webXml>
<classifier>${envClassifier}</classifier>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>snapshot</id>
<properties>
<envClassifier>snapshot</envClassifier>
</properties>
</profile>
<profile>
<id>release</id>
<properties>
<envClassifier>release</envClassifier>
</properties>
</profile>
</profiles>
Now, run command mvn clean install -Psnapshot Or mvn clean install -Prelease to get your desired artifacts. Hope this helps
You can control final war file name by warName attribute

Use specific xml files in production vs development

We have a maven based Spring Web-Application. All the web-calls are Restful and need authentication. But for development purpose, it is a pain to do all the needful. So for the development cycle, it is preferred to not have any security.
Using a maven flag or something, how do we generate separate builds for production and development?
All the security related stuff are in web.xml and applicationContext.xml. We can have 2 copies (one for development and the other for production). In the maven build, what is the simplest way to include the necessary files and omit others.
PS: I have seen examples of doing above using assembly plugin. I do not need all that but just a simple way to do it. I am using maven-war-plugin to generate war file.
Use profiles. You define them in your pom.xml (see below) and then when you build you include them. For command line this is simply
mvn -P <profile> <target>
most IDE's provide a way to set a profile.
pom.xml:
<properties>
<!-- default -->
<webXmlPath>src\main\webapp\WEB-INF\web-test.xml</webXmlPath>
</properties>
<profiles>
<profile>
<id>Production</id>
<properties>
<webXmlPath>src\main\webapp\WEB-INF\web.xml</webXmlPath>
</properties>
<build>
<finalName>${artifactId}</finalName>
</build>
</profile>
<profile>
<id>Accept</id>
<properties>
<webXmlPath>src\main\webapp\WEB-INF\web-accept.xml</webXmlPath>
</properties>
<build>
<finalName>${artifactId}-accept</finalName>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webXml>${webXmlPath}</webXml>
</configuration>
</plugin>
</plugins>
</build>

Building for local and production in IntelliJ using Maven

I have a simple spring mvc app, using maven with intellij.
How do you go about creating seperate files for both production and development?
e.g. say I want to set a production and development mysql connection string for nhibernate?
How can I have it such that when I build it will take the correct file to use to grab configuration information? (and any advice on naming conventions for the files?)
Using an ant task is pretty straight forward for this.
First, create a couple profiles under <project> in your pom:
<profiles>
<profile>
<id>build-dev</id>
<activation>
<!-- <activeByDefault>true</activeByDefault> -->
<property>
<name>env</name>
<value>dev</value>
</property>
</activation>
<properties>
<config.name>config.dev.properties</config.name>
</properties>
</profile>
<profile>
<id>build-prod</id>
<activation>
<property>
<name>env</name>
<value>prod</value>
</property>
</activation>
<properties>
<config.name>config.prod.properties</config.name>
</properties>
</profile>
</profiles>
Then use the maven-antrun-plugin
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete file="${project.build.outputDirectory}/config.properties"/>
<copy file="src/main/resources/${config.name}" tofile="${project.build.outputDirectory}/config.properties"/>
<delete file="${project.build.outputDirectory}/config.dev.properties"/>
<delete file="${project.build.outputDirectory}/config.prod.properties"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Now you just specify the profile you want when you run mvn. If you want a default, uncomment and place the:
<!-- <activeByDefault>true</activeByDefault> -->
section in the profile you want by default. As it is, the build will fail on the ant task if neither is specified.
There are a ton of ways to go about this.
In general, things like DB connection strings can go into property files, and replaced in the Spring XML configuration files using a PropertyPlaceholderConfigurer. One common-ish trick is to then create a custom implementation that looks for a -D startup parameter, a user name, a machine name, etc. that can be used to decide which property file to actually use.
The same trick can be used for the Spring configuration files as well by creating an implementation of an XmlWebApplicationContext (? I can never remember what to subclass) that adds/modifies the default getConfigLocations to add, say, files prefaced with a user or machine name, -D startup parameter value, and so on.
Btw, you're not using NHibernate if you're using Java, you're using Hibernate.
Edit Brian's approach is one of those "tons of ways", I just like to keep it configurable without building, i.e., dynamic based on arbitrary "local" conditions, etc. so I can swap things out really easily.

Categories