I have many jar files in my directory:
some-lib-2.0.jar
some-lib-2.1-SNAPSHOT.jar
some-lib-3.RELEASE.jar
some-lib-R8.jar
some-lib-core-1.jar
some-lib-2.patch2.jar
some-lib-2-alpha-4.jar
some-lib.jar
some-lib2-4.0.jar
How can I get library name and version from file name?
Is regex ((?:(?!-\d)\S)+)-(\S*\d\S*(?:-SNAPSHOT)?).jar$ valid for extract name and version?
The version number in the JAR file name is merely a convention and a default for Maven-built JARs. It may have been overridden, and it is not always reliable reading the version number from just the file name.
A more reliable way for reading version number from JAR is to look inside the JAR file. Here you have a couple of options depending on how the JAR was built:
look at META-INF/maven/.../pom.properies and pom.xml and read the version from that - this should be present for Maven-built binaries
sometimes version number if present in META-INF/MANIFEST.MF under Specification-Version or Implementation-Version properties
If this fails, then fall back to reading version number from the JAR name since there is no other information available.
Naming policy could differ across different libraries, so you aren't able to extract name/version from package name using one rule, for details you should check project docs.
In case of Maven you are able to configure the final name of built artifact with finalName pom.xml configuration option. Maven docs provide nice introduction into pom structure. Below is the example from docs:
<build>
...
<finalName>${artifactId}-${version}</finalName>
...
</build>
Related
This question already has answers here:
Unable to derive module descriptor for auto generated module names in Java 9?
(2 answers)
Closed 5 years ago.
I am trying to build a demo project in java 9 with maven that uses the dependency:
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-mllib_2.10</artifactId>
<version>2.2.0</version>
</dependency>
However when I run the jar tool to determine the automatic module name to use in my project's module-info.java I get the following error:
$ jar --file=spark-mllib_2.10/2.2.0/spark-mllib_2.10-2.2.0.jar --describe-module
Unable to derive module descriptor for: spark-mllib_2.10/2.2.0/spark-mllib_2.10-2.2.0.jar
spark.mllib.2.10: Invalid module name: '2' is not a Java identifier
It appears that the automatic module algorithm can't come up with a name that is valid java for this jar. Without adding the proper requires I get compile errors that the packages in spark mllib are missing such as:
package org.apache.spark.mllib.linalg does not exist
Is there anyway I can use this dependency in my project before it adds an official reserved module name or its own module-info?
For a proper, long-term solution the Apache Spark project must either add module declarations (module.info.java) to their JARs or set the Automatic-Module-Name entry in their JAR's manifest.
If you can't wait for that, you can do the latter yourself quite easily:
create a file manifest.txt with the following content:
Automatic-Module-Name: org.apache.spark.mlib2
Append that entry to the JAR's manifest:
jar --update --file spark-mllib_2.10.jar --manifest=manifest.txt
Make sure it worked:
jar --describe-module --file spark-mllib_2.10.jar
If you're planning to use this JAR in a real project, you would make it available to your colleagues, for which I would create a new version (maybe 2.10.patched-auto-name?), upload it to the company's Nexus and then edit the POMs to replace the original dependency with that one.
All in all, this is likely not worth the effort and you just might want to wait.
From the comments:
One thing to note is that the file you make the update with must end in a new line or the update silently fails.
When adding db2jcc4.jar to the system class path, Tomcat 8.0 raises a FileNotFoundException on a jar file that has no apparent reference to my project, pdq.jar.
I couldn't find it anywhere on my system or where it might come from, except through a search which turned up the answer below.
In this case, I have my CATALINA_HOME pointed to C:\tomcat8.0\apache-tomcat-8.0.41 and my project has the following maven dependency defined:
<dependency>
<groupId>com.ibm.db2.jcc</groupId>
<artifactId>db2jcc4</artifactId>
<version>10.1</version>
<scope>system</scope>
<systemPath>${env.CATALINA_HOME}/lib/db2jcc4-10.1.jar</systemPath>
</dependency>
This might happen in the newer versions of Db2 jcc driver:
Beginning with version 4.16 of the IBM Data Server Driver for JDBC and SQLJ, which is shipped with Db2 10.5 on Linux, UNIX, or Windows operating systems, the MANIFEST.MF file for db2jcc4.jar contains a reference to pdq.jar.
IBM Support offers 2 options:
Resolving the problem
To prevent the java.io.FileNotFoundException, you can take one of the following actions:
Edit the MANIFEST.MF file, and remove this line: Class-Path: pdq.jar
Edit the context.xml file for Apache Tomcat, and add an entry like the following one to set the value of scanClassPath to false.
Personally, I prefer the second approach, which can be done as following:
<Context>
...
<JarScanner scanClassPath="false" />
...
</Context>
According to this KB article on IBM, the problem comes from the MANIFEST, which lists pdq.jar, a third party optimization tool.
I had both db2jcc4.jar and db2jcc4.10.1.jar in my lib folder.
While the article suggests editing the MANIFEST file in db2jcc4.jar, version 10.1 does not include this entry at all.
Removing db2jcc4.jar solved my problem, so a solution in this case could also be to upgrade db2jcc4 from an older version to version 10.1, or if that is not possible, edit the manifest file as instructed.
You Just need to update jar db2jcc4.jar to be db2jcc4-10.1.jar
You can find maven dependency / Jar on that link
Kayvan Tehrani's answer explains what's going on here and that this error can be ignored.
Another alternative to clean up the logs is to create a dummy pdq.jar and place it into tomcat's lib folder.
jar -cf pdq.jar ""
(The ": no such file or directory" message from this command is expected.)
I would like to use derbyrun.jar created by the Apache Derby project in my application in order to run a derby database as a Windows or Linux service.
The problem is that derbyrun.jar references in its manifest other derby jars without any version number in their names, like Class-Path: derby.jar derbyclient.jar derbytools.jar derbynet.jar. While my application (with many subprojects) uses "maven/gradle" format derby-10.13.1.1.jar, derbyclient-10.13.1.1.jar, etc..
Is there a simple way in gradle to name those derby jars without a version number, like
compile("org.apache.derby:derby:10.11.1.1") {
artifact {
name = 'derby'
}
}
that should result in just derby.jar.
I do not like an idea of renaming derby-10.13.1.1.jar into derby.jar in a separate task as we reference those artifact names in many places using configurations.runtime, etc. (e.g. when deploying or creating manifest files for our own jars). And this renaming approach seems to complicate the script unnecessary (+ all the future maintenance effort when the derby version will be changed).
Is there a better way to achieve this? Sure, the mentioned above artifact { name = 'derby' } does not remove the version number from the jar's file name.
I have a multi-module maven project, including a seperate assembly-project. As i develop and run my application from eclipse (during development), i have specific configuration-files (e.g. log4j or other property-files) in my main-module (which contains the main-class). These files contain development-time-specific information. The assembly-project contains each of the config-files for production. The assembled product then should use these configs instead. This is my current setup:
MainModule/src/main/resources
+configA.properties
+log4j.properties
Module1/src/main/resources
+configB.properties
AssemblyProj/src/main/resources
+configA.properties
+configB.properties
+log4j.properties
And the generated project has this structure:
libs/
+MainModule.jar
+Module1.jar
configs/
+configA.properties
+configB.properties
+log4j.properties
the config-directory overlays the config-files in each *.jar because of the classpath, i.e.
java -cp configs/;libs/* My.Main.Class
Now the problem that i have, is that there are still all dev-configs included in each jar. Also i have kind of a bad feeling about using that overlay-classpath-method. Is there any practice on how to do this in a better manner?
Extract these resources into classifier-based dependencies for each of the mentioned modules. Then define <profiles/> that trigger their usage. In your assembly use the classifiers as necessary.
Let's say I have an ivy.xml that contains the following:
<dependency org="checkstyle" name="checkstyle" rev="4.3" />
And then I want to upgrade to Checkstyle 4.4, so I change my ivy.xml to contain:
<dependency org="checkstyle" name="checkstyle" rev="4.4" />
After a retrieve with the first configuration, I have the file checkstyle-4.3.jar. After the second configuration, I also have the file checkstyle-4.4.jar, and the file checkstyle-4.3.jar still exists.
Is there a way to have Ivy realize that the old file is an orphan, and remove it from the lib directory? The idea is that I don't want my developers' disk space usage to drastically increase every time I upgrade a tool.
Ideally I'd also want it removed from the local repository as well. I do realize that the intent of the local repository is that it is shared among projects, so it would not make sense to remove anything, as it would not know if the artifact was still in use in other projects. But there must be some kind of prune procedure...
I've been using Ivy 2.0.0, so I don't know if this applies to the version you're using.
The Ivy retrieve task has a sync attribute. Set this to true and unused/unknown files in your retrieved directory (lib in your case) will be removed. Keep in mind this will mean any manually copied artifacts in this directory which Ivy doesn't specifically resolve will be removed.
Also, note that if you use the sync option but Ivy resolves no dependencies (empty or missing ivy.xml, for example), the retrieve directory will be deleted.