I've been tasked with reducing the download size of one of our webstart apps. I've figured that a decent portion of the download is from all a largish library of jar files, and since we rarely update many of them, it seems the download will be reduced significantly using the JNLP Version Download Protocol. This should stop the continual re-download of the same jars when a new version of the app is released.
Now, the project is build with maven. Part of the process is automatically generating a JNLP file from a velocity template. The resources section of the JNLP file is populated by a $dependencies variable assumedly passed in by maven and looks something like this:
<jar href="lib/mainjar-0.1.40-SNAPSHOT.jar" main="true"/>
<jar href="lib/somejar-1.1.jar"/>
<jar href="lib/someotherjar-1.0.jar"/>
<jar href="lib/anotherjar-1.6.0.jar"/>
etc...
It seems to me that maven is using its standard naming convention and constructing the jar names from the artifactId and version tags out of the project pom files.
How can I get it to use the JNLP naming convention instead?
I can change the velocity template to cut the $dependencies variable up and re-combine it with the JNLP convention - but that's only halfway what I need since the actual jar names need to be changed too.
The version download protocol article is about speeding up the check that resources are up to date. Although it may be useful as well, it is not the part that prevents re-downloading of the same files.
Webstart-maven-plugin can take care of versioning of the jars for you and they declare they use the version protocol as well. See http://www.mojohaus.org/webstart/webstart-maven-plugin/jnlp-mojo.html#outputJarVersions
My personal experience differs from what the docs say. It adds the version attribute for jars in the resulting jnlp and does not set the jnlp.versionEnabled property, which seems to be required for the version download protocol. Either way JWS works as I would expect - files are not re-downloaded when their version does not change.
Plugin setup:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>webstart-maven-plugin</artifactId>
<version>1.0-beta-6</version>
<dependencies>
<!--This dependency definition resolves class loading issue on Java 8 -->
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>keytool-api-1.7</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>jnlp-download-servlet</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectoryName>/</outputDirectoryName>
<libPath/>
<sign>
<keystore>${basedir}/foo-key-store.jks</keystore>
<storepass>password</storepass>
<alias>foo-self-signed</alias>
<verify>true</verify>
</sign>
<unsign>true</unsign>
<jnlpFiles>
<jnlpFile>
<inputTemplate>template.vm</inputTemplate>
<outputFilename>foo.jnlp</outputFilename>
<jarResources>
<jarResource>
<groupId>foo.bar</groupId>
<artifactId>foo</artifactId>
<version>${project.version}</version>
<mainClass>foo.bar.Foo</mainClass>
<outputJarVersion>false</outputJarVersion>
</jarResource>
</jarResources>
</jnlpFile>
</jnlpFiles>
<gzip>true</gzip>
</configuration>
</plugin>
Excerpt from the generated foo.jnlp showing the version attribute of a dependency:
<jar href="commons-collections.jar" version="3.2.1"/>
And the file it references is named:
commons-collections-3.2.1.jar
Related
I'm trying to evaluate jetty for rapid development or project which is currently running on tomcat. My configuration looks like
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.3.v20140905</version>
<configuration>
<scanIntervalSeconds>3</scanIntervalSeconds>
<webApp>
<descriptor>${project.build.directory}/${project.build.finalName}/WEB-INF/web.xml</descriptor>
<resourceBases>
<directory>${basedir}/src/main/webapp</directory>
<directory>${basedir}/../SharedWeb/src/main/webapp</directory>
</resourceBases>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
<contextPath>/test</contextPath>
</webApp>
</configuration>
</plugin>
I have main war depending on SharedWeb war via war overlay mechanism. I specify resourceBases for both maven projects so changes in resources are scanned automatically and reloaded on the fly and all working fine. Also when I compile classes in main war, jetty restarts automatically, reloading the latest changes. But when I try to change any class in SharedWeb project and compile it, the class is not reloaded. I'm just wondering if there is a way to make embed jetty to reload classes from SharedWeb automatically? I understand that jetty-maven-plugin uses SharedWeb war from local maven repository, so I need to install SharedWeb artifact before I can see any changes. So I don't have high expectations, but maybe I'm missing something.
Ivan,
The plugin is using the classes and resources from your dependency
war, NOT from the that you have added. The
simply tells jetty to watch that location and redeploy if something in
it changes - it does NOT put it onto the classpath.
You need to tell jetty to use the classes and resources from your
dependency war's project, NOT the war artifact.
So do something like:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.3.v20140905</version>
<configuration>
<webApp>
<!-- tell jetty to use the classes from the dependency
webapp project directly -->
<extraClassPath>${basedir}/../SharedWeb/target/classes</extraClassPath>
<!-- tell jetty to use both this project's static
resources, and those of the dependency webapp project -->
<resourceBases>
<directory>${basedir}/src/main/webapp</directory>
<directory>${basedir}/../SharedWeb/src/main/webapp</directory>
</resourceBases>
</webApp>
<scanIntervalSeconds>3</scanIntervalSeconds>
<!-- tell jetty to watch the dependency webapp project classes
dir for changes -->
<scanTargets>
<scanTarget>${basedir}/../SharedWeb/target/classes/</scanTarget>
</scanTargets>
</configuration>
</plugin>
Jan
Since there doesn't seem to be a good prior answer that is specific enough for this question (aka <scanTarget>) I'll just post this new one and tweak the title to make it easier to find in the future.
What you are looking for is <scanTarget>, as that will allow you to customize the scanning locations for changed content that will trigger a hot redeploy.
The jetty-maven-plugin intentionally does not set this up for custom <resourceBases> as there are far to many legitimate use cases where this can cause aggressive / too often / or infinite redeploys. It was decided that it was best to break from "convention over configuration" for <scanTarget> entries and allow the developers to decide what should be scanned for changes.
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.3.v20140905</version>
<configuration>
...
<scanIntervalSeconds>3</scanIntervalSeconds>
<scanTargets>
<scanTarget>${basedir}/../SharedWeb/src/main/webapp/</scanTarget>
<scanTarget>${basedir}/../SharedWeb/target/classes/</scanTarget>
</scanTargets>
</configuration>
</plugin>
I want to use svn revision number of pom file as its version.
In pom.xml, if we use buildnumber-maven-plugin, we need to define scm repository url, so that it can check to repository and use buildnumber.
But i want to ask that when we have checkedout code to our system, isn't there any way to get buildnumber without using scm urls. As revision number is stored as subversion in property of each file. we can see it if we right click on file and go to properties.
I want to use buildnumber in version tag of pom and other module's buildnumber in their vaersion tag in dependencies to them.
So if i can store all subversion numbers initially, infact earlier than resolving dependencies, then these subversions can be placed in version of module in dependency and also in version of each pom file.
Problem is that dependencies are resolved before plugin reads version number ( this is what i think), so it cannot resolve expression.
I tried it using properties-maven-plugin to write pom's version number in a file and then read it in other module's pom which is dependent on it. But dependencies are to be resolved before execution of any plugin is started.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<id>pre-clean-config</id>
<phase>validate</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${project.basedir}/../app.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
So, it is not working.
Starting with Maven 3.2.1 you can define a property ${revision} which you can use in your versions like this:
<project...>
<groupId>..</groupId>
<artifactId>...</artifactId>
<version>1.0-${revision}</version>
...
The result of this you need to give a property while calling Maven like this:
mvn -Drevision=123456 clean package
This will also work in dependencies etc. Currently one drawback is that you always creating a release from maven's point of view.
I'm working with a situation where we are using the LATEST and RELEASE keywords in our POM for a certain dependency (both the dependency and the project are owned by us, so we control what is LATEST and RELEASE...and we only support one version at a time). Using these keywords allows us to minimize maintenance needed after a release.
There is a step in the build process that must copy DLLs from the unpacked dependency, but since we don't specify a specific version we have the version number of the unpacked dependency hard-coded and have to update it after every release. Is there a way get the version of this dependency at run-time from a Maven property?
The properties goal of the maven-dependency-plugin (http://maven.apache.org/plugins/maven-dependency-plugin/index.html) gets the location of the artifact in the local repository (which is not what I'm looking for). The depends-maven-plugin (shown here: http://team.ops4j.org/wiki/display/paxexam/Pax+Exam+-+Tutorial+1) can generate a file that contains the various dependencies and their versions, but using that would require having a process read the file and utilize that information. I'm wondering if there is a more "Maven way", such as accessing a property for the dependency version.
EDIT: For clarification, we need the version number so we can get to the directory of the unpacked dependency to copy files.
I'm not sure what you mean with 'maven way' but I did something like this after looking at the same plugins you already mention:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.properties.put('firstdependencyinthepom', project.dependencies[0]['version'])
project.properties.put('seconddependencyinthepom', project.dependencies[1]['version'])
</source>
</configuration>
</execution>
</executions>
</plugin>
and then I was able to refer to versions of these dependencies with ${firstdependencyinthepom} and ${seconddependencyinthepom} respectively.
I feel a bit stupid about this question but i can't figure out how to add a SINGLE dependency (jdom.jar) into another jar.
Context: We developed a simple plug-in for our application, this plug-in have many dependency. We were using fatjar to include jdom.jar into it. I am trying to fix a bug in this plug-in, so i decided to "maven-ize" it at the same time. (We just switched to maven) This plug-in is loaded on the runtime so the only dependencies we want packaged with it is the jdom.jar.
Problem: I found that there is a maven fatjar plug-in! Unfortunately i could not find any documentation and this maven plug-in add EVERY dependency into the ouput jar. After many try i decided to give up on this fatjar plug-in and searched for another one. I found one-jar , shade but after a quick read on them they look like they add every dependency.
Question: what would be a simple way to add only jdom.jar into my plug-in jar like this:
-MyPlug-in.jar
|
|-src
|-main
|-java
|-*.java
|-jdom.jar
Also I don't want to alter the manifest or the output jar filename
Thank a lots for your time.
There was no answer here regarding how to use maven to include one single jar-file with the maven-shader-plugin. It took me some time to figure out how to actually do that. Here is a snippet to include just the classes from the dependency com.googlecode.json-simple:json-simple.
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>com.googlecode.json-simple:json-simple</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
...
</project>
For this kind of purpose i would suggest to use the maven-shade-plugin which will create a ueber-jar which can be controlled in many ways.
With the shade plugin you can exclude things you don't like. But this might be caused by not using a separate maven module where you can control the dependencies.
Using maven Shade would work fine, one-jar would have done the job too.
But we finally decided that packaging jdom in our extension would be a bad practice.
So instead we gonna do this:
|-Root application Folder
|-Extension Folder
|-MyExtension.jar
|-libs Folder
|-jdom.jar
The jar into the lib folder will be loaded dynamically and won't be loaded if the extension cannot find the appropriate libs into the libs folder.
For the people who look to solve my primary problem please check out #khmarbaise Answer.
I currently have a Java testing library which is built with Maven, and distributed as a jar. My project depends on a very common library (Objectweb ASM), and I've experienced problems where an earlier and incompatible version of ASM is already on the classpath. Thus, I've started usings the jarjar-maven-plugin to create jar, repackaging ASM internally where it cannot conflict with another version of ASM.
This executes fine, and my library can be pulled in as a dependency with no problem.
However, because my project has compile-scope dependencies on ASM, whenever a client project adds my library, the transitive dependencies are all pulled in as well. So, hypothetically, if they use a particular version of ASM, and they also add the version I depend on to the classpath, they have undefined behaviour. I'd like to avoid this situation, and allow clients to depend on the JarJar'd artifact without having Maven pulling down the transitive dependencies both unnecessarily and potentially dangerously.
How do I create a JarJar'd artifact which users can depend on without pulling transitive dependencies?
I found a solution to this problem by ditching the jarjar-maven-plugin, and reverting to the maven-shade-plugin. This allows repackaging classes within your own namespace, setting the main class of the jar, and crucially, rewriting the generated pom to not include the compile time dependencies which are now bundled.
The part of my pom.xml which acheived this is:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>true</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.objectweb.asm</pattern>
<shadedPattern>${repackage.base}.org.objectweb.asm</shadedPattern>
</relocation>
</relocations>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${package.base}.my.MainClass</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
The important parts of this configuration are:
shadedArtifactAttached which when set to false, means the shaded jar will replace the main artifact that would normally be produced. This defaults to false but it's worth pointing out.
createDependencyReducedPom which when set to true means that when the shaded jar is deployed or installed, the pom.xml which is deployed will not include the compile-scope dependencies which have been repackaged into the jar.
relocation these elements configure how files within the dependencies are repackaged into the shaded jar. In the above example any class whose canonical name begins with org.objectweb.asm will be moved to ${package.base}.org.objectweb.asm, and thus when packaged in the jar will have the equivalent file path within the jar.
With this configuration, when my project is deployed, when clients declare a compile-scope dependency on my project, it only pulls in the shaded jar, and no transitive dependencies.
Consider trying the maven-shade-plugin instead, which allows all sorts of fine control.
Perhaps setting the <optional> attribute will work in your case. Specifying something like the following in your java testing library pom.
<dependencies>
<dependency>
<groupId>asm.group</groupId>
<artifactId>asm</artifactId>
<version>x.y</version>
<optional>true</optional>
</dependency>
...
</dependencies>