Maven archetype creation : prototype pom - maven

I am creating a maven archetype. In this I have a prototype project, which gets created for a user when the user calls the following command:
mvn archetype:generate -DarchetypeGroupId=xxx -DarchetypeArtifactId=archtype-yyyy -DarchetypeVersion=1.1.0-S5-SNAPSHOT -DgroupId=zzz -DartifactId=proj11
In the prototype pom, I want to use the 'archetypeVersion' property that I am specifying in the above command. Like this:
<dependencies>
<dependency>
<groupId>mmmm</groupId>
<artifactId>nte</artifactId>
<version>${archetypeVersion}</version>
</dependency>
This is not working for me. When the project is created, it still shows the dependency snippet in the generated pom exactly as it is posted above. It does not replace it.
Is this possible? Does maven allow this?
If yes, how can I do it?

I think simple way to do this is to use maven-replacer-plugin. You have to add next section to archetype /pom.xml:
<build>
...
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals><goal>replace</goal></goals>
</execution>
</executions>
<configuration>
<file>target/classes/archetype-resources/pom.xml</file>
<replacements>
<replacement>
<token>\$\{archetypeVersion\}</token>
<value>${version}</value>
</replacement>
</replacements>
</configuration>
</plugin>
</plugins>
...
<build>
ie this code replace ‘${archetypeVersion}’ substring to current version of archetype. Your ‘/src/main/resources/archetype-resources/pom.xml’ contains next dependency:
<dependency>
<groupId>xxxx</groupId>
<artifactId>yyyy</artifactId>
<version>${archetypeVersion}</version>
</dependency>
After executing ‘mvn install’ command, the resulting file ‘/target/classes/archetype-resources/pom.xml’ will be contain archetype version number. Now you have installed archetype and can use its: ‘mvn archetype:generate ...’.

Easiest way I've found is to just add it as a defaulted variable in your META-INF/maven/archetype-metadata.xml as follows:
<archetype-descriptor
xmlns="https://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.1.0 http://maven.apache.org/xsd/archetype-descriptor-1.1.0.xsd"
name="archetypeVersionExample">
<requiredProperties>
...
<requiredProperty key="archetypeVersion">
<defaultValue>${version}</defaultValue>
</requiredProperty>
</requiredProperties>
...
</archetype-descriptor>
No extra plugins or user entry needed.

Related

Running flyway commands from command line using spring boot properties for maven

I have a spring boot project using maven that I've included flyway in:
pom.xml:
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>6.5.0</version>
</dependency>
and application.properties:
#LOCAL
spring.datasource.url=jdbc:postgresql://localhost:5432/theDatabase
spring.datasource.username=theRightUser
spring.datasource.password=theRightPassword
and it works as expected when I run the application.
However, I'm trying to run mvn flyway:clean from the command line, and it doesn't seem to recognize the configuration correctly:
[ERROR] Failed to execute goal org.flywaydb:flyway-maven-plugin:6.4.4:clean (default-cli) on project my-service: org.flywaydb.core.api.FlywayException: Unable to connect to the database. Configure the url, user and password! -> [Help 1]
I tried adding spring.flyway properties (user/pass/url) in the application.properties file but it gave me the same error. What do I need to do to get flyway to read from the application.properies like it does when the application runs normally?
EDIT: I have made slight progress: I was able to reference my application.properties as a flyway config file by adding this to the pom.xml:
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>6.5.0</version>
<configuration>
<configFiles>${project.basedir}/src/main/resources/application.properties</configFiles>
</configuration>
</plugin>
So now in that file, I have flyway.url, flyway.user and flyway.password. This allows me to run flyway goals from the command line, but is not totally the solution I want. I am looking into using this plugin to try and read the properties into the pom.xml file, and then using those values in the flyway-maven-plugin's <configuration> area.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${project.basedir}/src/main/resources/application.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
which would allow me to do this:
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>6.5.0</version>
<configuration>
<url>${spring.datasource.url}</url>
<user>${spring.datasource.username}</user>
<password>${spring.datasource.password}</password>
</configuration>
</plugin>
When you run flyway as maven goal it will not pick up the properties from the application.properties, instead it will use the configuration provided by the flyway-maven-plugin, you can configure the flyway-maven-plugin in the following way -
Add the following plugin to pom.xml -
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>6.5.0</version>
</plugin>
Then we will configure the flyway-maven-plugin, the Flyway Maven plugin can be configured in a wide variety of following ways (most convenient),
Configuration section of the plugin
The easiest way is to simply use the plugin’s configuration section in your pom.xml:
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>6.5.0</version>
<configuration>
<driver>org.hsqldb.jdbcDriver</driver>
<url>jdbc:hsqldb:file:${project.build.directory}/db/flyway_sample;shutdown=true</url>
<user>SA</user>
<password>mySecretPwd</password>
<connectRetries>10</connectRetries>
<initSql>SET ROLE 'myuser'</initSql>
<schemas>
<schema>schema1</schema>
<schema>schema2</schema>
<schema>schema3</schema>
</schemas>
<callbacks>
<callback>com.mycompany.project.CustomCallback</callback>
<callback>com.mycompany.project.AnotherCallback</callback>
</callbacks>
<skipDefaultCallbacks>false</skipDefaultCallbacks>
<cleanDisabled>false</cleanDisabled>
<skip>false</skip>
<configFiles>
<configFile>myConfig.conf</configFile>
<configFile>other.conf</configFile>
</configFiles>
<workingDirectory>/my/working/dir</workingDirectory>
</configuration>
</plugin>
Maven properties
To make it easy to work with Maven profiles and to logically group configuration, the Flyway Maven plugin also supports Maven properties, update the properties section in pom.xml as follows:
<project>
...
<properties>
<!-- Properties are prefixed with flyway. -->
<flyway.user>myUser</flyway.user>
<flyway.password>mySecretPwd</flyway.password>
<!-- List are defined as comma-separated values -->
<flyway.schemas>schema1,schema2,schema3</flyway.schemas>
<!-- Individual placeholders are prefixed by flyway.placeholders. -->
<flyway.placeholders.keyABC>valueXYZ</flyway.placeholders.keyABC>
<flyway.placeholders.otherplaceholder>value123</flyway.placeholders.otherplaceholder>
</properties>
...
</project>
External Configuration File
Another way is to create a separate .properties file, the default configuration file name is flyway.properties and it should reside in the same directory as the pom.xml file. Encoding is specified by flyway.encoding (Default is UTF-8):
flyway.user=databaseUser
flyway.password=databasePassword
flyway.schemas=schemaName
...
If you are using any other name (e.g customConfig.properties) as the configuration file, then it should be specified explicitly when invoking the Maven command:
$ mvn <goals> -Dflyway.configFile=customConfig.properties
After configuring your flyway-maven-plugin, with the desired configuration, we will be able to execute flyway maven goals from command line.
You can do further reading here.
Hope this helps!

When does a Maven plugin uses the POM in the current directory?

I use the Versions Maven Plugin to check for updates of my dependencies. Therefore I added the following lines to my pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>${versions-plugin.version}</version>
<configuration>
<rulesUri>classpath:///rules.xml</rulesUri>
</configuration>
<dependencies>
<dependency>
<groupId>versionrules</groupId>
<artifactId>versionrules</artifactId>
<version>1-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
But this configuration is not used if I run the Versions Maven Plugin from the commandline in the same directory as the pom.xml. The only way to use my own configuration is to put this plugin configuration in a profil and execute this profil during the Maven run.
Is there a way to run the Versions plugin on the commandline and to configure it via the pom.xml? I am sure my questions does not only apply to the Versions plugin, but to any Maven plugin.
This can be done by using an execution id default-cli in your execution definition the configuration will be used during the execution on command line (using the current configuration) furthermore since Maven 3.3.1 you can use things like:
mvn version:set#second-cli
which means you can do a different configuration for command line in the pom file:
Just by simply separating them by different id
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.5.</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
...
</configuration>
</execution>
<execution>
<id>second-cli</id>
<configuration>
....
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
So this means you can have different configurations for running on command line by giving the id.

Can I have maven artifact run maven plugin when it is installed?

I have created a Maven plugin (called unpackTemplates) that unpacks a dependency jar file and copies resource files (in this case, templates) from it into a specific location in a project.
Right now, I put the following into the pom file of every project that has a dependency with templates. It looks like:
<project>
<groupId>DuriansAreDope</groupId>
<artifactId>DuriansAreDope</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugin>
<groupId>mycorp</groupId>
<artifactId>unpackTemplates</artifactId>
<version>1.0</version>
<executions>
<execution>
<configuration>
<groupId>com.mycorp.lib</groupId>
<version>1.0</version>
<artifactId>Lib-With-Templates</artifactId>
</configuration>
<goals>
<goal>unpackTemplates</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
</plugin>
<pluginManagement>....</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>com.mycorp.lib</groupId>
<artifactId>Lib-With-Templates</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
The above project pom works for us. It calls the plugin and the plugin does it's job. However, we'd like to avoid adding the plugin section to the pom of every project.
It would make more sense to put that plugin section in the dependencies pom. This way the project pom does not need to be modified beyond adding the <dependency> tags as usual. And the dependency has it's plugin run wherever it is installed.
I've seen that the pom file for Gson contains a <build><plugins>...</plugins></build> section in it. When I give my dependencies the following pom files, however, the plugin is not run (although the dependency is found, downloaded, installed, etc correctly).
<project>
<groupId>com.mycorp.lib</groupId>
<artifactId>Lib-With-Templates</artifactId>
<version>1.0</version>
<build>
<plugin>
<groupId>mycorp</groupId>
<artifactId>unpackTemplates</artifactId>
<version>1.0</version>
<executions>
<execution>
<configuration>
<groupId>com.mycorp.lib</groupId>
<version>1.0</version>
<artifactId>Lib-With-Templates</artifactId>
</configuration>
<goals>
<goal>unpackTemplates</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
</plugin>
<pluginManagement>....</pluginManagement>
</build>
</project>
Any ideas what I'm doing wrong, or if the Gson pom is simply doing something else entirely?
(NB: The groupId/version/artifactIds in <configuration> are necessary because they are (string) parameters to the plugin; presumably if I got the run-straight-from-dependency approach working I could refactor them away, but again, it's not even running the kludgy version with parameters.)
two points:
First I agree with khmarbaise in that you don't need a plugin of your own for those tasks. To unpack to a specific location you can use dependency:unpack-dependencies and outputDirectory parameter.
If you need more configuration you can use the assembly plugin to structure your artifact (which you want to unpack).
For the second point it seems to me that you want to use the contents of your lib-with-templates in many projects. Why don't you add the plugin and dependency to a parent pom which you include in every pom where you need it? Then you don't need to declare it in "every pom". If you don't really need it in every pom you can put it in a profile and choose a proper activation for it.
HTH!

Reading properties file values into pom.xml

I've tried and follow this solution
How to read an external properties file in Maven
but with no luck.
I would like to read an absolute path(/home/tomcat/lib) from a properties file(which is in the same location as pom.xml) and set the value in the pom.xml
project.properties file contains:
myTomCat.lib.location=/home/tomcat/lib
pom.xml configuration contains:
<properties>
<envTomcatLib>${myTomCat.lib.location}</envTomcatLib>
</properties>
<dependencies>
<dependency>
<artifactId>MyJar</artifactId>
<groupId>MyJar</groupId>
<scope>system</scope>
<version>1.0</version>
<systemPath>/${envTomcatLib}/MyJar.jar</systemPath>
</dependency>
</dependencies>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${basedir}/project.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
The problem is either at eclipse compile time or running "mvn install" that the placeholder ${envTomcatLib}/MyJar.jar, can't get resolved to /home/tomcat/lib/MyJar.jar and remains ${envTomcatLib}/MyJar.jar.
Can someone please assist?
Thanks
Values in the <properties> section are assigned when the POM is initially loaded. The properties-maven-plugin only affects plugin executions that come after the point where the properties were loaded. More detail in a similar answer I provided.
BTW, the Maven Reference Book has this to say about system scope: "Note that this scope is not recommended (you should always try to reference dependencies in a public or custom Maven repository)."
You may need to remove "/" before /${envTomcatLib}/MyJar.jar or give property value as home/tomcat/lib instead of /home/tomcat/lib. It may be the reason for not able to resolve your location.

docbkx-maven-plugin: No output during run of plugin

I set up the docbkx-maven-plugin to generate PDF documentation for a source project. In the parent pom I specified the version to be used as well as the reference to the docbook version to use:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
<version>2.0.14</version>
<dependencies>
<dependency>
<groupId>net.sf.docbook</groupId>
<artifactId>docbook-xml</artifactId>
<version>5.0-all</version>
<type>zip</type>
<classifier>resources</classifier>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</pluginManagement>
In the actual project I use the configuration:
<build>
<plugins>
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
<executions>
<execution>
<id>usersmanual</id>
<phase>generate-resources</phase>
<goals>
<goal>generate-pdf</goal>
</goals>
<configuration>
<includes>${basedir}/UserManual/*.xml</includes>
<includes>${basedir}/UserManual/src/*.xml</includes>
<targetDirectory>${project.build.directory}/UserManual</targetDirectory>
<chunkedOutput>true</chunkedOutput>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
No matter what goal(s) I specify or what includes I provide, the plugin performs no(!) operation. There is no target directory created and I do not see any meaningful output on the command line. The result looks like:
[INFO] --- docbkx-maven-plugin:2.0.14:generate-pdf (usersmanual) # documentation ---
[INFO]
I use Maven 3.0.3.
What do I miss here? Is there any configuration not provided, yet, which will start the plugin to do some work?
UPDATE:
This is what I have now:
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
<version>2.0.14</version>
<dependencies>
<dependency>
<groupId>net.sf.docbook</groupId>
<artifactId>docbook-xml</artifactId>
<version>5.0-all</version>
<type>zip</type>
<classifier>resources</classifier>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>generate-pdf</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<sourceDirectory>${project.basedir}/UserManual</sourceDirectory>
<xincludeSupported>true</xincludeSupported>
<includes>${project.basedir}/UserManual/UserManual.xml</includes>
<includes>${project.basedir}/UserManual/**/*.xml</includes>
<targetDirectory>${project.build.directory}/UserManual</targetDirectory>
</configuration>
</execution>
</executions>
</plugin>
At least the directory target/Usermanual is greated, but it is still empty. Why is there still not output? Do I have a chance to get a meaningful log file from docbkx? mvn ... -X does not tell much.
Your latest example contains two includes configuration options which is not valid maven configuration.
My recommendation is to stop trying to override all these defaults and accept the default location for the docbook source xml, at least initially while you get comfortable with the plugin and can diagnose what issues are from what changes.
Anyway, your <includes> should be just the root xml file of the documentation you're trying to generate as it exists in the <sourceDirectory>. You do not need to include all of the xml files, you instead need to follow the xincludes approach since you're declaring its usage. There are a number of projects using this mechanism that you can review and copy the usage of.
Ours is: https://github.com/jetty-project/jetty-documentation
We have a bit more complex usage since we use the maven filtering plugin to avoid having to mess with entities and the like. Getting back to your includes usage, if your top level docbook file is index.xml then your includes would simply be:
<includes>index.xml</includes>
No expressions or globs needed, you bring in the other xml documents with the <xi:include> tags where needed.

Resources