How do I prompt for user input in Maven? - java

I'm writing a Maven plugin which I'd like to prompt for a simple user input and decide whether to halt the plugin's execution.
I'd like to do something like this:
$> mvn myplugin:run
[MAVEN] would you like to continue? [default value: y] _
I've tried using maven-antrun-plugin as described here, but in this case Maven gets user input when I build my plugin. Instead, I'd like to retrieve input when user is running my plugin from within some other app that has declared my plugin (confusing?)

Use a Prompter component and have it injected in your plugin (assuming you are using Maven plugin annotations, if not use the equivalent javadoc tags):
#Component
private Prompter prompter;
And to use it:
String name = prompter.prompt("Please enter your name");
Pull in this dependency in your plugin's POM:
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-interactivity-api</artifactId>
<version>1.0-alpha-6</version>
</dependency>
The prompter component is used by the release plugin for prompting the user for tags and versions and the archetype plugin as well.

Don't do this. If you need to supply data to a mojo, do it via configuration.
The behavior of your Maven build should be entirely predictable based on your POM and the goals & options supplied to the Maven command line. If you allow a user to feed in additional information during the build, your POM no longer completely describes your project.
Also, it would prevent any automated build server doing its job.

as variant, to not break maven way as wool.in.silver wrote, you can use shell script that will prompt values and then call maven with gathered values as parameters

Related

How to ignore a dependency in dependency-lock-maven-plugin

In my maven project I want to implement dependency-locking.
One approach I've found is using dependency-lock-maven-plugin.
My project has multiple maven modules.
parent
core
service
third-maven-module
When I run mvn clean package it will generate a new core-0.0.1-SNAPSHOT.jar every time.
Now apart from checking version dependency-lock-maven-plugin also checks SHA, which in this case gets changed every time & then the plugin throws error stating SHA is different.
Now to avoid this in plugin's version 0.0.78f56707b3a1d639c8e769bba1686587e9a8956 we can simple add below lines:
<configuration>
<ignore>
<dependency>com.myservice:core:*</dependency>
</ignore>
</configuration>
It works but now I can see that this version has vulnerabilities, so I want to use the latest version 1.0
But it looks like the configuration to ignore a dependency has been changed & documentation does not says much.
Please suggest how can I ignore a dependency in dependency-lock-maven-plugin.

Which lifecycle for a Java annotation that generates documentation?

I would like to be able to document the dependencies of my services directly in my code, using Java annotations. Those annotations could bear the information about the target system, whether the connection is incoming/outgoing/2-ways, and the type of connection (REST, RabbitMQ...).
It could look like this:
#Dependency(target = "Twitter API", type = "Outgoing", medium = "REST")
The idea would be to generate a DOT file from all the annotations inside the project.
I have a fair idea on how to create my own annotation, with the required attributes. However, i am not sure at which part of the lifecycle of the compilation/processing i should handle those annotations.
I understand that the annotation processors generate source files, but in my case the generated files are not at all required by the compiler nor the application itself.
Ideally i would like to be able to trigger the annotation processing, and DOT file generation, by a dedicated Maven or Gradle task.
Is it something that is easily doable when writing my own annotations?
If you want to create documentation via maven than you need add the bellow two dependencies as plugins and then execute site maven goal.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
If you just want to document REST endpoints than you can use swagger.
If your project uses spring than the integration of swagger is pretty easy. You can use this tutorial.
If you want to save in a file the dependency graph of your project you can simply execute the following maven command.
mvn dependency:tree -Doutput=/path/to/file
Annotations are processed by the Java compiler directly.
For Maven, one can use the maven-compiler-plugin. It is also possible to perform the compilation in 2 steps, as explained here.
For Gradle, one can add the processors in the dependencies block under the annotationProcessor configuration, as explained here.
Annotation retention can be specified as SOURCE, so they won't be kept after compilation.

Accessing Jenkins environmental variables through a custom mojo

Is it possible to do this?
For example could one do something like:
System.getEnv("$(env.BUILD_URL)");
I do not have access to Jenkins, so can't try it out myself :(
Any help would be greatly appreciated.
Assuming you're using Maven (you've tagged this question as such), I simply add the following to my pom.xml file:
...
<properties>
<!-- Hudson properties: see http://wiki.hudson-ci.org/display/HUDSON/Building+a+software+project#Buildingasoftwareproject-HudsonSetEnvironmentVariables -->
<jenkins.buildId>${env.BUILD_ID}</jenkins.buildId>
<jenkins.buildNumber>${env.BUILD_NUMBER}</jenkins.buildNumber>
<jenkins.buildTag>${env.BUILD_TAG}</jenkins.buildTag>
<jenkins.cvsBranch>${env.CVS_BRANCH}</jenkins.cvsBranch>
<jenkins.executorNumber>${env.EXECUTOR_NUMBER}</jenkins.executorNumber>
<jenkins.hudsonUrl>${env.HUDSON_URL}</jenkins.hudsonUrl>
<jenkins.javaHome>${env.JAVA_HOME}</jenkins.javaHome>
<jenkins.jobName>${env.JOB_NAME}</jenkins.jobName>
<jenkins.svnRevision>${env.SVN_REVISION}</jenkins.svnRevision>
<jenkins.workspace>${env.WORKSPACE}</jenkins.workspace>
</properties>
...
...and then from your code you can simply do a:
String url = System.getProperty("jenkins.hudsonUrl"); // could be null
Putting these into properties makes life more simple for my purposes, especially when using Maven profiles to control my builds. For example, I make sure to create a "jenkins" profile that is activated when I build on a Jenkins build server. When this is done, all the aforementioned jenkins properties are set. When not run as a jenkins profile, those properties are set to some other default value. Anyway, that's another topic, but food for thought. Hopefully it make sense.

Set maven property from plugin

I've read some questions here about how to set a property (most of them talked about the version number for an application) from a maven plugin.
It seems there's no easy way of doing this and the best solution I found is to have a filter.properties file which is updated from the plugin and used by the main pom file to filter the desired resources.
I tried another solution after I read this from the Maven documentation (Maven filter plugin):
Variables can be included in your resources. These variables, denoted
by the ${...} delimiters, can come from the system properties, your
project properties, from your filter resources and from the command
line.
I found interesting that variabled can be read from system properties. So, I modified my plugin to set a system property like this:
System.setProperty("currentVersion", appCurrentVersion);
However, filtered resources don't seem to read this value.
Could anybody tell me what's wrong with this approach?
UPDATE: I'm running my plugin in the validate phase.
Thanks a lot.
Don't set it as System Property, set it as Maven Project property
// inject the project
#Parameter(defaultValue = "${project}")
private org.apache.maven.project.MavenProject project;
// and in execute(), use it:
project.getProperties().setProperty("currentVersion", appCurrentVersion);
See:
Mojo Developer Cookbook
MavenProject javadoc
An edit suggested using Properties.put() instead of Properties.setProperty(). While technically, Properties implements Map, this usage is discouraged explicitly in the Properties javadoc.
Maven sets properties in initialize phase. I assume that in that phase maven loads system properties. And after that maven doesn't load system properties again. If you try to add a system property after this phase than it's not loaded.
Try to run your plugin in validate phase.

Credentials ignored with maven scmchangelog-plugin

When I configure the scmchangelog-plugin, as written in the examples/tutorial, and run the site-generation, the username and password I have set are ignored.
The documentation says that username and password which should be used to access the SCM can be configured in the plugin-configuration. This looks like this:
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>scmchangelog-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<grammar>REMY</grammar>
<connectionUrl>scm:svn:svn+ssh://repo.lan/repo/project/trunk</connectionUrl>
<username>user</username>
<password>password</password>
</configuration>
</plugin>
</plugins>
</reporting>
When i run the site-generation (mvn site), the output on the commandline says
[INFO] Executing: /bin/sh -c cd /tmp && svn --username user --password '*****'
--non-interactive list --xml svn+ssh://repo.lan/repo/project/tags/
But I'm still prompted for the the password and the user used to access the SCM is the one running the mvn command.
Any ideas what could be wrong?
Update:
I tracked down the problem to the svn command line client now.
the problem is, that when i run a command like the following
svn list --username foo --password bar --non-interactive svn+ssh://host/repo/project
the command line tool seems to ignore the given options. i'm still questioned for a password, and the user used to access the URL is the one who executes the command, and not the one set in the options.
i'm using svn version 1.4.6 here.
any ideas what might go wrong here ?
This is a known bug. The correct behavior would be to show an error that states that the --username and --password options are not supported when using an external authentication mechanism like SSH, instead of silently ignoring those options.
To fix your issue, pass your 'foo' username as part of the URL:
svn+ssh://foo#host/repo/project
and use something like ssh-agent to cache your credentials, thus avoiding the password prompt.
Do you mean the scm:changelog goal of the Maven SCM plugin? If this is the case you have two choices to ensure the SCM is passed your credentials.
Preferred approach
Some SCM providers allow you to specify a settings file below M2_HOME/conf/.scm, for example Subversion's is svn-settings.xml and CVS's is cvs-settings.xml
Your SCM provider should define how to define the configuration settings. For Subversion I end up with a file like this:
<svn-settings>
<user>[username]</user>
<password>[password]</password>
</svn-settings>
If needed, you can specify the SCM settings file in another location by passing a command-line parameter to the file:
-Dmaven.scm.svn.config_directory=your_configuration_directory
Other approach
The other (undesirable) option is to configure the scm section of the POM so that the urls contain the username and password. The implementation of this is provider-specific, but is generally of a similar form to this example for Subversion:
scm:svn:http://[user]:[password]#host/path
So your scm section in the POM would look something like this:
<scm>
<connection>scm:svn:http://[user]:[password]#host/path</connection>
<developerConnection>
scm:svn:http://[user]:[password]#host/path
</developerConnection>
<url>http://somerepository.com/viewsvn</url>
</scm>
This is obviously undesirable as your SCM credentials end up in your installed POM, you should really only use this for testing the connection in my opinion. For more information see the SCM URL Format page and details for specific SCM providers
Check if there's an alias clobbering your use of the "svn" command.
Also check if the destination host allows password-mode authentification. Might also be worth to check that the desktop doesn't fool around with some handy "keyring agent", those can interfere with svn+ssh.

Categories

Resources