How to find hidden jar in classpath? - java

I have a web app with Spring, Hibernate and Struts 2 and I get this error:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.NoSuchFieldError: TRACE
So I googled it, found this wich says:
if you are on the Equinox Console, perform the following check:
packages org.apache.log4j
Which I did, and got this:
org.apache.log4j; version="1.2.15"<org.apache.log4j_1.2.15.v201005080500 [33]>
org.apache.velocity_1.5.0.v200905192330 [37] imports
And I don't really know what that means... But what I'm sure of is that jar is NOT the one I'm supposed to be using.
In fact, I ran the packages command after I deleted all the log4j jars in the project and in the Tomcat libraries.
And even after deleting the log4j jars, I can still import the org.apache.log4j.Level class in any class in my project (and of course that Level class that I can import doesn't have the TRACE field).
So, how do I find where it is? And how does it get included in my project classpath???
Thank you for your time!

Try following to find location of the jar causing the issue:
System.out.println(org.apache.log4j.Level.class.getProtectionDomain().getCodeSource().getLocation());

The jvm argument '-verbose' or '-verbose:class' will output on the console for each class where it is loaded from (in most cases which jar). Possibly this is available to you (depending on how you run the webapp).
For log4j keep in mind that many people ship log4j with their jar. Ideally they should change the package name if they do that, but some don't. I wrote/assembled the following bash script to find which jar I used had log4j in it:
for file in *.jar
do
unzip -l "$file" 2> /dev/null | grep "log4j.dtd" && echo $
done
This looks for log4j.dtd which I was looking for (feel free to replace with any log4j class) and then prints the path in the zip file and after that the name of the zip file that contains it. Just run it from the directory with all your jars.

Related

How to fix "NoClassDefFoundError" with BCrypt (org.mindrot.BCrypt)?

I try to create a Minecraft Plugin (it's my first one) and I can't fix this error:
So, the plugin compiles good but when the code has to execute this code :
BCrypt.checkpw(mdp, result.getString("mdp"))
that come from the lib org.mindrot.BCrypt, I have this error :
Caused by: java.lang.NoClassDefFoundError: org/mindrot/BCrypt
But, when I open my JAR with WinRAR, there is my lib bcrypt (so it's well export). And it's also in my .classpath.
Can you help me ?
Thanks.
There are several ways to configure the CLASSPATH when launching a java application via the java command. According to what you posted so far, I would use the -classpath flag:
java -classpath spigot.jar;jbcrypt.jar class.containing.main.method.MyMain
Alternatively, you could modify the MANIFEST in file spigot.jar. Refer to Adding Classes to the JAR File's Classpath.
Or you could copy jbcrypt.jar to the directory pointed to by the java System property "java.ext.dirs".

How can I dynamically use externalized properties file with Spring jar?

With this setup (from Eclipse using Windows10)
I was able to correctly start my SpringBoot application. This one worked too (same directory pattern):
Now I'm packaging my project as JAR and I want to use an external properties file. I had an teste32.yml file beside my JAR at the same directory (also tried to use it inside /config directory, as show here, but it didn't work either)
I want to dynamically use a properties file beside my JAR file everytime. Doesn't matter at which directory they are, I wanted to dynamically point to a properties file always at the same directory as the JAR is. I want to say to my client: "take this JAR and this file, put them wherever you want and run this command X and everything will be alright". I'm trying to discover command X but before I add some dynamic path, I'm trying with absolutes paths. I'm using this:
java -jar myJar.jar -Dspring.config.name=teste32 -Dspring.config.location=C:\workspace\myProject\target\
I manually copied teste32 inside target\ to test this. But this didn't work. This didn't work either (only spring.config.location variants):
-Dspring.config.location=file:C:\workspace\myProject\target\
-Dspring.config.location=classpath:/
-Dspring.config.location=file:C:/workspace/myProject/target/
I also tried with no spring.config.location, only name
So my questions are:
What does classpath: and file: mean? Until now I got the 2 correct setups by pure luck and I would like to understand when to use them.
When I have my project package as a JAR, what classpath becomes?
Finally, which combination is necessary to dynamically use a properties always at the same directory as the JAR?
UPDATE
Using --debug at the correct example got me this line at the very begging (Spring banner was still visible):
2018-09-25 15:45:14.480 DEBUG 11360 --- [ main] o.s.b.c.c.ConfigFileApplicationListener : Loaded config file 'file:src/main/resources/xirulei/teste32.yml' (file:src/main/resources/xirulei/teste32.yml)
But after moving myJar.jar and teste32.yml to a specific directory and running java -jar myJar.jar -Dspring.config.name=teste32 --debug (without spring.config.location, since teste32 is at the same directory as JAR), I simply didn't get any ConfigFileApplicationListener debug line.
a) java -jar myJar.jar -Dspring.config.name=teste32 -Dspring.config.location=C:\workspace\myProject\target
Did you check content of target dir? I'm pretty sure your cfg file is placed to target\classes\xirulei and it is why Spring cannot find it in target
b) When you place teste32.yml in the same directory as jar file then Spring must be able to find it (given this directory is working directory) without -Dspring.config.location (but you still need to provide -Dspring.config.name=teste32)
c) When you use -jar and do not provide additional class paths then classpath: points to the root of packages inside jar. Spring cannot find your file at classpath:/ because your file is at classpath:/xirulei/
Well, after all it was a simple mistake. As documentation says and as already pointed here, it should be
java -jar myproject.jar --spring.config.name=myproject
and not
java - jar myproject.jar -Dspring.config.name=myproject
As stated on question, only when using Eclipse -D(JVM argument) is necessary. When using bash/cmd, just --(program argument) is the correct option:

jdeprscan throws cannot find class error

I'm trying jdeprscan on my CentOS system. Here are the commands that I'm executing:
export classpath=<PATH/*>:<ANOTHER/PATH/*>:<SOME/OTHER/PATH/*>
jdeprscan --for-removal --verbose --class-path $classpath --release 9 <ANOTHER/PATH>/MyProject.jar
In spite of providing the classpath, I'm getting multiple errors of this sort
Processing class <some/class/in/MyProject.jar>...
error: cannot find class <some/class/in/a/different/jar>
error: cannot resolve Methodref <some/class/in/a/different/jar>.<method>:()Ljava/lang/String;
I've verified that the class mentioned in the error message are pretty much among one of the jars provided in the classpath.
Strangely, it's not the case that I'm getting this error for every other classes referred in the jar that I'm scanning.
Few points for your consideration:
The are 50+ jars in the paths provided in the classpath
The jar that I'm trying to scan is residing in one of the paths mentioned in the classpath
I've tried jdeprscan available in JDK 9 & JDK 10 and getting the same errors
I've tried replacing the * in classpath with *.jar, doesn't help!
Is there anything wrong in the syntax that I'm following or is this a known bug in jdeprscan?
Some preliminary notes on jdeprscsan from Oracle JDK 11 under Windows (I know the question related to JDK 9 on CentOS, but maybe the following applies as well...):
use wildcard "path/to/lib/*.jar" (it will not work without the ".jar" extension)
having a wildcard with more than one path is not supported (i.e. --class-path dir1/;dir2/*.jar throws a parse exception on the wildcard)
JARs in the directory specified by --class-path are added to the classpath and analyzed in alphabetical order, which may cause some error : cannot find class X messages because a JAR a.jar may depend on a JAR b.jar which is not yet loaded.
Based on the above, I found the 3 solutions below. Note that I did the same experiment with jdeprscan from the Oracle JDK 12.0.2 without any improvement.
Solution 1: all classes on the classpath
unzip all JARs in a specific directory (ignore overwritted files such as META-INF/maven/pom.xml), e.g. mylib (note that at this stage, the mylibs directory contains only classes organized by directory packages, and no JARs).
run the following command:
jdeprscan --for-removal --class-path /path/to/mylib /path/to/my-application.jar
Advantage: fast (very manual operations)
Drawback: only analyses the JAR file that has been specified on the command line (my-application.jar)
Solution 2: all JARs + a fat JAR on the classpath
copy all JARs libs into a single mylib directory
extract all files from JARs of mylib (ignore duplicate files) and repack them into a big JAR mylib/00lib.jar (a simple ZIP file renamed to .jar makes the trick)
copy the mylib/00lib.jar to mylib/01lib.jar to ensure that it will be analysed
run the following command:
jdeprscan --for-removal --verbose --class-path path/to/mylib/*.jar path/to/my-application.jar
Advantage: fast (only a few manual operations) + analyses the JARs from mylib
Drawback: some of the jdeprscan messages will be related to the fat JAR 00lib.jar so you will not be able to determine immediately which library uses classes that are deprecated or removed from Java 9 or 11, but you can do it indirectly by looking at the class name, e.g. (a class from the com.atomikos library requires the missing class javax.jms.JMSException):
Processing class com/atomikos/datasource/xa/jms/JmsTransactionalResource...
error: cannot find class javax/jms/JMSException
Solution 3: reorder the JAR files on the classpath
copy all JARs libs into a single mylib directory
run the following command:
jdeprscan --for-removal --class-path path/to/mylib/*.jar path/to/my-application.jar
inspect the log to see error: cannot find class messages that are not supposed to be raised because the JAR exists in the lib directory. For each such library, copy the library with a name that is before the library name which reference it alphabetically speaking. For example, I have a JAR in the lib dir alpha.jar which depends on commons-lang-3.0.jar (which is not yet loaded in the classpath), so I copy commons-lang-3.0.jar to a0commons-lang-3.0.jar so that it will be loaded before alpha.jar. It is important to copy the JAR and not to rename it otherwise it may not be analyzed by jdeprscan (does not occur on every JAR). Once done, go back to step 2 until no error messages produced by library dependencies occurs.
Advantage: gives a clear view of which JAR uses deprecated/removed classes.
Drawback: takes a lot time (manual copy of each individual JARs which cause a classloading issue).
Conclusion
I use jdeprscan with Solution 2. This should be considered as a workaround (is it an incomplete tool documentation or a bug, I don't know...).
If you happen to have a folder in PATH which has classes and JARs, it won't work. You'd have to specify the JARs individually (or get rid of the classes).

How to import commons-io.jar jsp/java

I am getting an exception:
Cannot find symbol: FileUploadException;
I have a piece of code which uses
FileUploadException
The library that needs importing is:
org.apache.commons.fileupload.FileUploadException
The path to my project is :
D:\Projects\website
In the project folder I have each in its folder:
Tomcat, Derby, Website
I have copied:
commons-fileupload.jar and commons-io.jar
into both:
Tomcat/lib and Website/Web-INF/lib
---------------I tried this--------------
just importing the library on its own
import org.apache.commons.fileupload.FileUploadException;
adding the jars to the class path upon build:
javac -cp .;D:Projects\website\Tomcat\lib\commons-fileupload.jar;D:\Projects\website\Tomcat\lib\commons-io.jar com/otrocol/app/*.java
adding them to the Environment variables CLASSPATH
D:Projects\website\Tomcat\lib\commons-fileupload.jar;D:\Projects\website\Tomcat\lib\commons-io.jar
I also tried adding the jars where my .java files are as #Scot Ship suggested
----mentions---
I am not using any IDE
The code contains more unrecognized symbols, but I'm trying to solve one at a time
First time using apache, tomcat, jsp.. please be gentle
Vlad, the web container will automatically look for JARs inside
/WEB-INF/lib
even without any developer intervention. Take note that it's all caps WEB-INF. As long as your JAR is there, it will be in your web application's classpath.
Try to display this in one of your servlets or JSP:
System.getProperty("java.class.path")
and you'll get a better view of what classes and JARs were actually loaded.
Update: After reviewing your question, it appears you're facing issues in compiling the files to begin with and you're doing it outside an IDE.
Take note that when you use -cp in javac like this:
javac -cp .;D:Projects\website\Tomcat\lib\commons-fileupload.jar;D:\Projects\website\Tomcat\lib\commons-io.jar com/otrocol/app/*.java
Whatever value you have set in the CLASSPATH environment variable becomes ignored.
Be absolutely sure that the class FileUploadException is indeed inside one of the JARs you're trying to import: you can view the JAR directly using an unarchiving tool.
Also, change the com/otrocol/app/*.java to com\otrocol\app*.java - you should be using your system delimiter (not that this may affect your problem).
Create a simple HelloWorld in the same location as the file you're compiling, add the SystemOut mentioned above, and compile it the same way you're doing for the concerned file.
Read this http://commons.apache.org/proper/commons-fileupload/faq.html#class-not-found. Probably you have the fileupload jar but you also need commons-io.jar in your classpath as well.

How to configure External tool in Eclipse to run a jar file and load other class files?

In Eclipse Indigo (on Mac OSX), I have a project 'Test'. In this project I have a package 'test1'. In this package, I have a class Test.java.
In short the file structure is: Test/src/Test.java and
Test/bin/Test.class
I have a library mylib.jar in lib folder.
I also have a data file named info.dat. In info.dat, there's information about which class to load. For example, in info.dat, I specified: class=Test
then, when I run:
$ java -jar lib/mylib.jar info.dat
(NOTE: this works if I run this command in terminal and have class file in the same folder with info.dat)
the main function in mylib.jar will load Test.class.
I'm using External Tools to achieve this. Here is my External tool setup:
Location: /usr/bin/java
Working Location: /path/to/Test_folder
Argument: -cp . -jar lib/mylib.jar bin/test1/info.dat
However, when I try to run, I get this error:
LOADING INFO FROM FILE bin/test1/info.dat
=> Current directory=[not include because not important]
=> Full pathname=[not include because not important]
java.lang.ClassNotFoundException: Test
I also tried to change class=test.Test in info.dat but got a similar error
java.lang.ClassNotFoundException: test1.Test
The result shows that the info.dat was loaded ok, but the path to class file was not correct. How should I configure the external tool to do what I need? Can someone please give me some instruction?
Many thanks,
It was an easy solution with Run Configuration. I just need to pick the main class from mylib.jar in Java Application and put info.dat in the argument field.
Sorry for wasting the resource here.

Categories

Resources