As the header says I wonder if there is such an opportunity in Maven to know the jar a class file gets loaded in a module. Just like dependency:tree, but I would like to see jars with a specific class file. Thanks!
As far as I know, there is no specific Maven plugin (3.0+) that will search dependencies for class declarations. However, I believe I understand your need and offer the following solutions:
Finding duplicate declarations
mvn dependency:analyze-duplicate -DcheckDuplicateClasses
Find containing JAR within Eclipse
Use CTRL+SHIFT+T to bring up the Open Type dialog. Entering part or the whole class name presents a list of containing JARs on the build classpath.
Find containing JAR without IDE
If more programatic control is required for checking on systems without an IDE, say a CI server, the following snippets can be used to list JAR files containing a specific class or even a specific name pattern. This approach uses Maven's dependency plugin to collect all dependencies in a temporary directory such that they may be easily searched.
For Unix or Git Bash systems
mvn clean dependency:copy-dependencies -DoutputDirectory=target/temp
for j in target/temp/*.jar; do jar -tf $j | grep SomeClass && echo $j; done
For Windows via cmd shell
mvn clean dependency:copy-dependencies -DoutputDirectory=target/temp
for /R %G in (target\temp\*.jar) do #jar -tf "%G" | find "SomeClass" && echo %G
In either case, a matching entry's full package and class name will be displayed followed by the containing JAR file name. grep and find search parameters can be further refined to restrict matches as needed, such as SomeClass.class.
Hope this helps.
Related
QUESTION
I am not a maven pro and I got stuck trying to package a Kafka Connector. There are two options for packaging it:
Either you produce a folder with a jar that contains the connector + all the dependency jars - all the kafka-specific jars
Or build a fat jar with all of the dependencies (and I also assume without the kafka-specific jars again, but it is not explicit in the docs).
I am following docs on confluent webpage and the connector I am trying to package is this one on github.
What I tried, after cloning the repo with git, is the following mvn clean package. But this seems to create only a single jar of the original project with the dependencies in mvn cache (~/.m2/repository/).
Google also has link on how to create a fat jar, but I would need somehow to specify which jars I want to exclude from the fat jar.
Thanks
UPDATE
Now I am running:
connect-standalone /etc/kafka/connect-standalone.properties /etc/kafka/connect-cdc-mssql-source.properties
Where /etc/kafka/connect-standalone.properties contains the following line:
plugin.path=/shared_win_files
And ls -al /shared_win_files contains the following:
kafka-connect-cdc-mssql-0.0.1-SNAPSHOT.jar
And jar tvf kafka-connect-cdc-mssql-0.0.1-SNAPSHOT.jar contains the following:
6996 Thu Sep 07 14:47:24 BST 2017 com/github/jcustenborder/kafka/connect/cdc/mssql/MsSqlSourceConnector.class
where MsSqlSourceConnector.classis basically this class here which implements the Connector.
But when I try to run the connector with the command above, I get an error
Failed to find any class that implements Connector and which name matches com.github.jcustenborder.kafka.connect.cdc.mssql.MsSqlSourceConnector
It gives a massive list with all available plugins, but mine is not in there.
Currently, an easy way to package your connector with maven is to use maven-assembly-plugin. This basically entails two main steps:
Define one or more assembly descriptors and save them under src/assembly.
Doc: http://maven.apache.org/plugins/maven-assembly-plugin/descriptor-refs.html
Example: https://github.com/confluentinc/kafka-connect-elasticsearch/blob/master/src/assembly/package.xml
In the descriptor, among other things, you may choose the packaging format of your archive, files and directories to include or exclude, as well as specific settings regarding your projects dependencies.
Include the plugin in your project's pom.xml
Example: https://github.com/confluentinc/kafka-connect-elasticsearch/blob/master/pom.xml
This mainly requires you to define the configuration and execution sections of the maven-assembly-plugin section. Additionally you can associate calls to specific assembly plugin descriptors with certain maven profiles that you may define.
Finally, stay tuned because packaging your Kafka Connect plugins (connectors, transforms, converters) might be significantly simplified soon.
Following Konstantine's answer how to package jars.
The remaining problem was that when specifying plugin.path=/abc in KafkaConnect config, you have to be careful.
You can either put a fat jar like this:
/abc/fatjar.jar
Or you have to create another folder in abc and put all the related jars into that folder like this:
/abc/my-connector-a/connector.jar
/abc/my-connector-a/connector-dependency.jar
...
As in my case, it was treating jars as separate plugins.
How do I add .java files to my jar?
My classes, in the bin/ folder, are like:
aaa/b/c/program.class and /aaa/b/c/d.class
So I add a/ to the jar and set the entry point to aaa.b.c.Program.
Then I can: java -jar foo.jar
and the program runs.
If I jar up the src/aaa/* and bin/aaa/* files, it isn't able to find aaa/b/c/Program.class - I tried several ways of specifying the entry point. It seem that the path must match the package+class name.
What's the proper way to make the jar file?
It won't let me add the java and class paths to the same folders easily.
If I go to the parent folder and add the files:
jar -cef x.jar aaa.b.c.Program -C src aaa -C bin aaa
I get : : : java.util.zip.ZipException: duplicate entry: aaa/
To get them in the same folders, I can do it in two steps:
jar -cef x.jar aaa.b.c.program -C bin aaa
jar -uf x.jar -C src aaa
Is this the proper way?
If there are docs, do I put them in the same folders, too?
I searched a bunch on the web and am not finding this,
even (especially?) in the lame Oracle docs...
(I tried to get Eclipse to do it- but it won't let me leave some classes out... But I really want to do this with the command line...)
Thanks
If you want to have the compiled classes and the sources in the same folders, then you have to use two steps, a jar cf step to create the file with one set of files, and a jar uf step to add the other set of files, as in your example.
But doing this is not recommended. The recommended practice is to separate the runnable, the sources and the docs, and use a dedicated jar file for each. As you're doing something unusual, it's no surprise that there's no easy way to do it (you need two steps).
I have an Eclipse setup with m2eclipse and subversive. I have imported a maven2 project from svn. But I get the error message that a whole bunch of artifacts are missing (for instance: Missing artifact org.springframework:spring-test:jar:3.0.1.RELEASE:test).
If I look in my repository I see the jar files there but they have an extra extension .lastUpdated. Why is maven appending .lastUpdated to the jars? And more importantly: how can I fix this?
There is no mention of the type lastUpdated in my POMs.
These files indicate to Maven that it attempted to obtain the archive by download, but was unsuccessful. In order to save bandwidth it will not attempt this again until a certain time period encoded in the file has elapsed. The command line switch -U force maven to perform the update before the retry period. This may be necessary if you attempted to build while disconnected from the network.
The method of removing the files works with most versions of maven, but since the files are internal mementos to maven, I would not recommend this method. There is no guarantee that this information is not referenced or held elsewhere and such manipulation can damage the system.
As rperez said, I use to delete all those .lastUpdated files. In Linux I have created a little script to keep it simple:
find -name \*.lastUpdated -exec rm -fv {} +
Just create a file with the previous content and put it on your local Maven repository. Usually it will be ~/.m2/repository.
I installed Maven2 and ran mvn compile from the command line. This seems to have resolved the problem
you might have a problem with some of the artifacts to be retrieved from the repository. for example spring framework has its own repository. this xtension is appended when the artifact cannot fully downloaded. add the spring framework repository to your pom or settings.xml, delete the folder that include the broken jars and start again
If you hit this problem and you're using Nexus, it might be the case that you have a routing rule defined, which is incorrect. I hit this myself and the files it was downloading were correctly named, at the proper URL-s it was looking at, but they were all with the .lastUpdated extension and an error message as contents.
Open your terminal, navigate to your Eclipse's project directory and run:
mvn install
If mvn install doesn't update your dependencies, then call it with a switch to force update:
mvn install -U
This is a much safer approach compared to tampering with maven files as you delete ".lastUpdated".
Use this command inside the .m2/repository dir to rename all files:
for file in `find . -iname *.lastUpdated`; do renamed=$(echo $file | rev | cut -c13- | rev); echo renaming: $file to $renamed; mv $file $renamed; done
This is usefull to not download all sources again.
This not work... The .jar is lost. :(
What I do when I encounter this issue:
Make sure you have the version of the latest 'maven-source-plugin' plugin:
https://maven.apache.org/plugins/maven-source-plugin/usage.html
$ mvn source:jar install
Now if the file *.lastUpdate exist in your local ~/.m2/repositories/your-lib/0.0.1/ directory you can just remove it then run the command above again.
This is a side-effect of a failure to successfully extract from the repository. To get the actual content you want into your repository, check for correct paths to the repository/repositories within your pom file, and resolve certificate/security issues, if any. It is almost invariably one or the other of these issues.
There is no need to delete the .lastUpdated entries, and doing so won't solve your problem.
Is there a plugin or a tool that I can use to quickly delete all <version> tags from a pom defn?
I have a a few multi-module projects with some 50-80 modules, each with a <version> tag. However, they each inherit from a common parent, so I would rather remove all <version> definitions in each module pom and have it inherit the version from the parent.
Search & Replace will obviously delete any tags in plugins, dependencies, etc.
Is there something that exists that will do this quickly for me instead? For the moment, I find myself editing each file individually, which is time consuming.
After a bunch of head scratching, I came up with a fairly simple method.
Using the versions-maven-plugin, I was able to recursively go through each module in my application and set the version to some known string. Then after that, it becomes an easy Search and Replace to remove that one string.
Ex:
find . -name pom.xml -exec mvn versions:set -DnewVersion=9999_TO_DELETE_9999 -f {} \;
then it becomes a simple Search and Replace to delete the <VERSION>9999_TO_DELETE_9999</VERSION> string.
Care must be taken to exclude the parent pom from the find command otherwise it will update the parent pom version in all the modules as well.
Maybe not as elegant as Groovy, but fairly quick and easy.
I would like to use Maven to produce an artifact in zip format. To give you some background; my project includes an APS package (Application Packaging Standard, used to provision cloud applications on the Parallels platform). This package is a zip file that contains a combination of XML as well as PHP files. It is generated by an APS plugin from within Eclipse and its name always includes the version and release number of its contents.
What I am trying to do is generate a zip file with Maven that would be kind of a release candidate that will be eventually sent to customers and would include not only the actual APS package but also other files such as README, User Guide.pdf, etc;. I would like the name of this zip file to contain the version number of the version number of the APS package. Currently I can generate this manually by using something like "mvn -Dversion=1.2.3-4 package" but I would like to automate the process and ideally run this from Jenkins.
Basically, my strategy is to run a script that would extract the version number from the initial APS package, once that is done, my script can invoke Maven and can pass this parameter to it so it can generate the final zip with the proper version number. This is fine but again, I need to run this script manually and I am looking for an automated process.
My question is; is it possible to invoke this script from within Maven and use its return as a parameter to set the version name (or the name of the file that will be generated) at run time? As I mentioned, I would like eventually Jenkins to handle this. It can pick up the pom file but I am not sure how it could kind of "auto configure" itself to have the proper version number.
Thanks is advance.
From jenkins build you can use profile with ${BUILD_NUMBER}:
<profile>
<id>jenkins</id>
<build>
<finalName>${artifactId}-${version}-${BUILD_NUMBER}</finalName>
</build>
</profile>
Then run in jenkins:
clean install -Pjenkins
I use the SVN (or any source versioning system) version to identify the software builds.
By simply executing this
REVISION=`svn info | grep '^Revision:' | sed -e 's/^Revision: //'`
on the sourcers folder you get the right value in $REVISION, then you can use it for your maven build
mvn -Dversion=1.2.3-$REVISION package
easy and clean