Maven project variables for dependencies - java

I have an html file which loads an applet. The html needs to refer to the jar by name, and since maven names it based on the artifactid, version, etc, the html needs to be dynamically updated as the project evolves. It seems like resource filtering is the way to go, but I can't figure out what the variable to interpolate should look like. I'd like something along the lines of ${project.dependencies.myartifactid.version}, but that doesn't seem to be an option and I've had woeful luck googling.

You'll need something like ${project.dependencies[0].artifactId} where 0 is the index of the dependency of the applet in your war module (see PLXUTILS-37). And indeed, using resources filtering should work.
Update: It appears that there is bug in the Maven Resources Plugin, this property doesn't get filtered as mentioned in this question. You may have to use the workaround suggested in this answer.

As I understand it you are trying to keep the version up to date, while expecting the rest to stay the same. There are two alternatives.
The first is to remove the version from the name so that the HTML need not change. You can see a practical example by searching for archiva-applet here: https://github.com/apache/archiva/blob/archiva-1.3/archiva-modules/archiva-web/archiva-webapp/pom.xml
In this example, since you don't want the applet in WEB-INF/classes anyway, it is omitted from the webapp, and then included via the Dependency plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<id>copy</id>
<phase>process-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>archiva-applet</artifactId>
<version>${project.version}</version>
<outputDirectory>src/main/webapp</outputDirectory>
<destFileName>archiva-applet.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
If you are using Maven 2.1.0+ you can use the prepare-package phase and copy it straight to the output without modifying your source directory.
You then refer to the applet in HTML with the single name.
An alternative solution if you want to continue filtering and keep the version, is to use a shared property:
<properties>
<applet.version>1.2.3</applet.version>
</properties>
...
<dependency>
<groupId>my.group</groupId>
<artifactId>my.applet</artifactId>
<version>${applet.version}</version>
</dependency>
...
You can then use ${applet.version} in the HTML and still only have to change it in one place.

https://cwiki.apache.org/confluence/display/MAVEN/Maven+Properties+Guide
${project.build.finalName} This is by default defined as ${project.artifactId}-${project.version}
Another option you have is to change set ${project.build.finalName} to a static string in your POM:
<build>
<finalName>foo</finalName>
</build>

Related

Versions Maven Plugin rules that are inheritable

When running mvn versions:display-dependency-updates for the Version Maven Plugin I see lots of things like this:
[INFO] org.slf4j:slf4j-api ........................... 1.7.36 -> 2.0.0-alpha7
But just because I'm not using the alpha version of a later version doesn't mean I'm not using the latest available release version. Another Stack Overflow answer indicated that I can set up a rules.xml file to ignore versions like *.-alpha*, putting something like this in my POM:
<configuration>
<rulesUri>file:///${project.basedir}/rules.xml</rulesUri>
</configuration>
My question: is this rules.xml file inheritable? If I put it in a separate project in a parent POM of <packaging>pom</packaging>, published to Maven Central, will the child POMs pick it up? Or will the child projects look for a rules.xml file in the child project directory?
I want to configure the versions-maven-plugin in the parent POM (as I do already) and run mvn versions:display-dependency-updates on any child POM or descendant POM. How can I set up the ignore rules in the parent POM so that these version ignore rules will be picked up when I check for dependency updates in a child POM? (Is there no way to include the rule within the POM itself?)
Or will the child projects look for a rules.xml file in the child project directory?
Yes, if you define the rules.xml file via ${project.basedir} it will resolve to the current local base directory of the child project. I've verified this with a simple parent-child pom setup. So that will not work, unless you duplicate the rules file in every project.
If you wish to include the plugin configuration and ruleset in the parent pom without duplicating the rules file, you have two options:
If you have your ruleset xml file hosted at, for example, http://www.mycompany.com/maven-version-rules.xml then the following configuration in your corporate pom would ensure that all projects use this rule set.
<configuration>
<rulesUri>http://www.mycompany.com/maven-version-rules.xml</rulesUri>
</configuration>
or
You can provide your ruleset xml file also within a jar, if you want to distribute your ruleset xml as Maven artifact. Therefore you have to declare the containing jar as direct dependency of the versions-maven-plugin and to use classpath as protocol.
<configuration>
<rulesUri>classpath:///package/foo/bar/rules.xml</rulesUri>
</configuration>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>version-rules</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
Source:
https://www.mojohaus.org/versions-maven-plugin/version-rules.html
The configuration in the pom only has rudimentary includes and excludes filters. Those will allow you to exclude any dependency as a whole, but not specific update versions. As far as i can tell from the available documentation there is no way to define version rules in any other way.
See
https://www.mojohaus.org/versions-maven-plugin/examples/advancing-dependency-versions.html
Update 09-2022
In the github ticket we found in the comments we can see the following update:
It looks like a feature like this has recently been implemented by #369. Please see #318 where it's possible to provide inclusion and exclusion filters for determining which dependency patterns will be considered. Thanks to that, you can rule out patterns such as .*-beta. or .*_ALPHA, albeit not using regexp, but simple asterisk wildcards.
This will land in today's release (2.12.0).
This will add the following features:
Version 2.12.0 will introduce new arguments: dependencyIncluded, dependencyExcludes, dependencyManagementIncludes, dependencyManagementExcludes.
With the following example configuration in pom.xml given:
<profile>
<id>display-dependency-updates</id>
<build>
<plugins>
<plugin>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>display-dependency-updates</goal>
</goals>
<configuration>
<dependencyIncludes>org.apache.maven.*:doxia*</dependencyIncludes>
<dependencyManagementIncludes>com.puppy*:*</dependencyManagementIncludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
This will also be implemented for filtering plugin and pluginManagement, but that will probably be added in a later release:
So, I've just added the missing plugin- and plugin management filtering which works likewise. I really doubt it will land into today's release though.
Pasting my answer here from Github, because I think it might benefit others.
Provided you have a directory called rules-test in your project containing the rules template file:
<ruleset comparisonMethod="maven"
xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0
https://www.mojohaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<ignoreVersions>
<ignoreVersion type="regex">${ignoredVersions}</ignoreVersion>
</ignoreVersions>
</ruleset>
Then, in your main project, create the following profile:
<profile>
<id>rules-test</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>rules-test</directory>
<filtering>true</filtering>
</resource>
</resources>
<outputDirectory>${project.basedir}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.12.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>display-dependency-updates</goal>
</goals>
<configuration>
<rulesUri>file://${project.basedir}/compiled-rules.xml</rulesUri>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
If you then execute the following Maven target:
mvn -P rules-test "-DignoredVersions=.*-(M\d*|.*-SNAPSHOT)" clean validate
then you will get a dependencies report using the filter in the -DignoredVersions argument (filtering out both *-M* and *-SNAPSHOT).
And if you put your ignoredVerions property in your project instead of passing it as a -D argument, then it will be inheritable!

What is the usage of JSP compiler?

Recently I started working on a maven based Struts project using JSP and Java 7.
I see the dependency in pom as following.
<plugin>
<groupId>org.jasig.mojo.jspc</groupId>
<artifactId>jspc-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<directory>${basedir}/src/main/webapp/</directory>
<includes>
<include>**/*.jsp</include>
</includes>
</sources>
<includeInProject>false</includeInProject>
<validateXml>false</validateXml>
</configuration>
<dependencies>
<dependency>
<groupId>org.jasig.mojo.jspc</groupId>
<artifactId>jspc-compiler-tomcat8</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.5.3</version>
</dependency>
</dependencies>
</plugin>
I removed it and build project successfully. The UI of application works fine.
Can someone please help me in understanding the usage of this plugin?
JSP pre-compilers avoid a JSP compilation delay when a JSP page is first hit.
It is an optimization that may or may not be actually worth it, but for high-page-count high-usage sites that use server-side HTML generation it may be worth it.
For example, see https://www.mulesoft.com/tcat/tomcat-jsp
Meta
Questions like this can be self-answered by searching the web. The first step is to identify what you're looking at, which it appears you did, since you identified the dependency as a JSP compiler.
Once you know what you're trying to look for, ask the web "why use a JSP compiler" or something similar. The reference I posted above was one of the early results when I searched for this.

Is there a way to refer, with Maven, specific elements within a dependency or artifactItem?

Currently, I have a pom.xml, which, upon build, gathers dependency Javadoc jars from mvnrepository and unpacks them in specific folders:
<build>
<finalName>${parent.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-javadoc-jars</id>
<goals>
<goal>unpack</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>groupid1</groupId>
<artifactId>artifactid1</artifactId>
<version>1.0.0</version>
<classifier>javadoc</classifier>
<outputDirectory>${project.build.directory}/dependency-javadoc/artifactid1-1.0.0</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>groupid2</groupId>
<artifactId>artifactid2</artifactId>
<version>2.0.0</version>
<classifier>javadoc</classifier>
<outputDirectory>${project.build.directory}/dependency-javadoc/artifactid2-2.0.0</outputDirectory>
</artifactItem>
...
</artifactItems>
</configuration>
</plugin>
</plugins>
</build>
The thing is, if I do not specify the output directory field for each artifact, the javadoc gets unpacked all in one folder (which is also configurable for the unpack goal - https://maven.apache.org/plugins-archives/maven-dependency-plugin-2.6/unpack-mojo.html ), and I want them to be clearly structured in folders. So I added a directory entry for each artifactItem. However, I have to write the folder name manually. Is there a way to refer the existing artifactItem's fields, in a way similar to this:
<artifactItem>
<groupId>groupid1</groupId>
<artifactId>artifactid1</artifactId>
<version>1.0.0</version>
<classifier>javadoc</classifier>
<outputDirectory>${project.build.directory}/dependency-javadoc/${artifactItem.artifactId}-${artifactItem.version}</outputDirectory>
</artifactItem>
This way,I will be able to just copy/paste the outputDirectory in all javadoc artifact entries, but it will be the same.
Thanks!
This is an interesting question. I remember having had this requirement of using POM declarations as properties in the same POM in the past, but I hardcoded the values then since there were just a few of them. However, I think we're out of luck here. At least with the approach that came into my mind first:
Writing a Maven Plugin like e.g POM Strings Maven Plugin (and in fact I did that here for a POC of my idea) with a goal:
pom-strings:toProperties -Dxpath=//artifactItems/*/text()[normalize-space()]
which finds all XML text nodes (under <artifactItems> in your case) in the POM, then finds their full XML tree paths and creates Maven project properties for them that look like:
/project/build/plugins/plugin/configuration/artifactItems/artifactItem/artifactId=...
/project/build/plugins/plugin/configuration/artifactItems/artifactItem/version=...
After declaring its execution at e.g. the initialize phase of your projects your declarations will look like (with line breaks for easier reading):
<outputDirectory>
${project.build.directory}/dependency-javadoc/
${/project/build/plugins/plugin/configuration/artifactItems/artifactItem/artifactId}
-
${/project/build/plugins/plugin/configuration/artifactItems/artifactItem/version}
</outputDirectory>
The problem, however, is this inconspicuous, innocent "...", since the full paths are not unique in this case. There are two possible values for each of them. To resolve this a key would have to be introduced (by finding the first unique parent) so that the properties will look like:
/project/build/plugins/plugin/configuration/artifactItems[<key1>]/artifactId=artifactid1
/project/build/plugins/plugin/configuration/artifactItems[<key1>]/version=1.0.0
/project/build/plugins/plugin/configuration/artifactItems[<key2>]/artifactId=artifactid2
/project/build/plugins/plugin/configuration/artifactItems[<key2>]/version=2.0.0
If this key would be a numerical index the declaration order would be crucial, which contradicts the declarative nature of POMs and for that it's not the Good, but the Bad and the Ugly[1]:
/.../artifactItems[0]/artifactId=artifactid1
/.../artifactItems[0]/version=1.0.0
/.../artifactItems[1]/artifactId=artifactid2
/.../artifactItems[1]/version=2.0.0
If this key would be an associative textual key, the question is which value should be taken and if this is decidable somehow you would have to do what you wanted to avoid originally: hardcode the <artifactId>s (or <version>s, or whatever ensures uniqueness):
/.../artifactItems['artifactid1']/artifactId=artifactid1
/.../artifactItems['artifactid1']/version=1.0.0
/.../artifactItems['artifactid2']/artifactId=artifactid2
/.../artifactItems['artifactid2']/version=2.0.0

Can Maven re-sign dependencies?

I'm using maven-jarsigner-plugin to sign a shaded uber-jar of mine. I do need to distribute some dependencies in their own jars though, and want to take those jars from a Maven repo, clear them of any existing signatures, and sign them with my own certificate.
Are there any Maven plugins that do this, or would i involve some Ant plugin hackery?
Turns out maven-jarsigner-plugin can re-sign existing jars using it's removeExistingSignatures config element. So simple!
I use maven-dependency-plugin to copy artifacts into a .war project in the generate-resources phase, then sign them in the process-resources phase.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.lwjgl.lwjgl</groupId>
<artifactId>lwjgl-platform</artifactId>
<version>2.9.0</version>
<classifier>natives-osx</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>src/main/webapp/</outputDirectory>
<destFileName>lwjgl-platform-natives-osx.jar</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>src/main/webapp</outputDirectory>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>sign</id>
<phase>process-resources</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<keystore>${basedir}/path/to/my.keystore</keystore>
<alias>alias</alias>
<storepass>password</storepass>
<keypass>password</keypass>
<verbose>true</verbose>
<archiveDirectory>src/main/webapp/</archiveDirectory>
<processMainArtifact>false</processMainArtifact>
<removeExistingSignatures>true</removeExistingSignatures>
</configuration>
</plugin>
I know it is not a really good answer, but I would try a solution in these steps:
copy dependencies by maven-dependency-plugin
antrun: <unzip> them, strip everything from /META-INF directory except MANIFEST.MF, <jar> again and sign them again by using <jarsign> ant task.
The main problem I have found since I work with maven (quite recently I admit) is that it makes you go through its predefined pipeline, and this kind of things (which is more common than it seems) will make you need some ant hackery as you call it ;)
Never used it, but it seems the webstart-maven-plugin can unsign and sign jars.
http://mojo.codehaus.org/webstart/webstart-maven-plugin/unsign-mojo.html
Hope this help.
Using maven:
Create an empty maven jar module per jar that you want to resign, do a maven dependency:unpack of one of the jars, filtering the signature files and copying the files to src/main/java.
Then sign the jar with maven-jarsigned-plugin, the result will be a jar containing the same classes.
An alternative non-maven based:
The above way does not scale well, it would probably be simpler to create a script that follows these steps.
The simplest way to do it would be:
Instead of resigning the jars, consider registering the public key of the signer in your maven repository, meaning you trust the person that created these jars and accept any jars coming from them.
The truth is you already trust them since you are using their code and resigning it, so it would be simpler to configure the repository to accept their signature, in the same way that the repository was already configured by someone to accept your signature.
The repository is linked to a key store containing the public keys of the accepted jar signers, it would be a matter of asking the team that handles the repository to add one more key to their list of trusted signers, they would know how to do that for sure.

In Maven2, is there a way to scope a dependency to "package only" and keep it off the test classpath?

Setup
I'm packaging a WAR with a number of legacy jar dependencies in it (for the sake of keeping this simple, they can not possibly be altered or excluded from the deployed WAR).
Issue
Including either or both of two of these jars will cause inexorable errors at test-time. If I exclude the dependencies altogether, the tests pass happily, but the WAR will lack real-world runtime classes it needs.
Hope
Maven2 offers compile, test, runtime, system, and provided scopes. Sadly, none of these will be included in the assembly but kept off the test classpath. My hope is that I'm missing some obvious way to handle this case entirely within the dependency management feature.
Fear
I'll have to use the assembly plugin to copy these problem jars into the target. I don't want to have to skirt the dependency management system to copy jars in the clear into the target, as I don't want to manage these jars outside the internal repository.
Thoughts? Alternatives?
Of course it figures that I'd come across a potential solution to this moments after posting a question. It appears that the copy goal of the dependency plugin may handle this. Going to try this out now: http://maven.apache.org/plugins/maven-dependency-plugin/usage.html
Edit: Turns out that this worked fine for my needs, snippet below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>group</groupId>
<artifactId>artifact</artifactId>
<version>version</version>
<type>jar</type>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</plugin>
Break the test classes out of the jar file into a separate jar which is only for tests, and add an exclusion to the dependency on the jar with the legacy dependencies.

Categories

Resources