Solved

Commons-logging+jUnit - Bizzarre problem - may be JVM bug?

Posted on 2004-04-19
21
1,091 Views
Last Modified: 2011-04-14
This is really odd.

I have some jUnit test cases.  When i run them under the JBuilder TestRunner and the text TestRunner, everything is fine.  When I run them under the Swing TestRunner, they blow up because the logger interface casting check fails.

We are using the common-logging interface and log4j.

The exact method that is failing is org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor().

The exact point of failure is this snip:

            if (!Log.class.isAssignableFrom(logClass)) {
                throw new LogConfigurationException
                    ("Class " + logClassName + " does not implement Log");
            }

logClass is org.apache.commons.logging.impl.Log4JLogger.

I have confirmed both by code review and by visually checking the instance in the debugger (during a cycle where the test fails) that logClass implements the org.apache.commons.logging.Log interface.

I have confirmed that I am using exactly the same class path for all three test runners.

I have ensured that I only have one version of Log4J and commons-logging on my box.

I get the same results with JRE 1.4.1, and 1.4.2.
0
Comment
Question by:swift99
  • 10
  • 9
  • 2
21 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 10861735
>>they blow up because the logger interface casting check fails

What exactly is the error that shows?
0
 
LVL 6

Author Comment

by:swift99
ID: 10861766
The exact error is:

org.apache.commons.logging.LogConfigurationException: Class org.apache.commons.logging.impl.Log4JLogger does not implement Log.

I have traced into the commons-logging package and comfirmed that it is executing the snip of code identified in the original message.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10861791
>>does not implement Log.

Make sure you pass the fully-qualified (inc package) class name into the method
0
 
LVL 6

Author Comment

by:swift99
ID: 10861832
If this were the problem, then wouldn't the text and JBuilder test runners display the same behavior?

I have confirmed visually that the logClass is <org.apache.commons.logging.impl.Log4JLogger> both when the test succeeds and when it fails.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10861840
i.e.

if (!Log.class.isAssignableFrom(Class.forName("org.apache.commons.logging.Log"))) {
}
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 125 total points
ID: 10861852
>>If this were the problem

Could be down to different class loading behaviour. Give the above a try - it can't do any harm - and we can go from there
0
 
LVL 6

Author Comment

by:swift99
ID: 10861864
This code is part of the apache commons-logging package.  While modification is technically feasible, it should not be necessary.  This package, and its initialization code, is used without alteration by thousands of java apps around the world.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10861907
>>This code is part of the apache commons-logging package

Do you mean it's their source!? If so then you need to do


Class classToTest = Class.forName("org.apache.commons.logging.Log");

and then pass it to their code

The trouble is, there are so many logging implementations around, if you are not very careful with packages and f.q. names you can get conflicts.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10862005
If you pass -verbose

java -verbose YourMainClass

you should see where your classes are being loaded from in each case
0
 
LVL 6

Author Comment

by:swift99
ID: 10862320
Here's something odd from the verbose printout - see the last three lines.

It appears that two versions of Log are being loaded (!?)

[Loaded org.apache.commons.logging.LogFactory]
[Loaded org.apache.commons.logging.LogConfigurationException]
[Loaded java.io.UnsupportedEncodingException from D:\DevTools\JBuilder9\jdk1.4\jre\lib\rt.jar]
[Loaded java.lang.SecurityException from D:\DevTools\JBuilder9\jdk1.4\jre\lib\rt.jar]
[Loaded org.apache.commons.logging.LogFactory$1]
[Loaded org.apache.commons.logging.LogFactory$3]
[Loaded org.apache.commons.logging.LogFactory$2]
[Loaded org.apache.commons.logging.impl.LogFactoryImpl]
[Loaded org.apache.commons.logging.impl.LogFactoryImpl$1]
[Loaded org.apache.log4j.spi.AppenderAttachable]
[Loaded org.apache.log4j.Category]
[Loaded org.apache.log4j.Logger]
[Loaded org.apache.commons.logging.Log]
[Loaded org.apache.commons.logging.impl.Log4JLogger]
[Loaded org.apache.commons.logging.Log]

0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 86

Expert Comment

by:CEHJ
ID: 10862345
What about the 'from' bit though?
0
 
LVL 6

Author Comment

by:swift99
ID: 10862494
Now THAT was   interesting ... Under text TestRunner, the JDK14 logger class is used - not the Log4J class.

I think that explains what is different, but not _why_ it is different.  Thanks for the ammo for more research.
0
 
LVL 6

Author Comment

by:swift99
ID: 10862501
There was no "from" bit for the logging packages.  What you see is what I got.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10862548
>>Now THAT was   interesting ...

This is precisely the sort of thing i was talking about. Double check the classpath being used in each case
0
 
LVL 6

Author Comment

by:swift99
ID: 10862575
The class path is identical.  The batch file was copied and the junit.textui.TestRunner was changed to junit.swingui.TestRunner.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10862592
>>The class path is identical.  

I thought in one case JBuilder was being used? It constructs its own classpath
0
 
LVL 6

Author Comment

by:swift99
ID: 10862747
Yes ... it is the ultimate origin of all other classpaths.
0
 
LVL 92

Accepted Solution

by:
objects earned 125 total points
ID: 10864559
Your problem is probably caused by multiple versions of a library being available to the class loader.
0
 
LVL 6

Author Comment

by:swift99
ID: 10868911
Well ... we were all on the right track.

The jUnit swing TestRunner, under some circumstances, loads the classes twice.  Turning off the "Reload classes every run" checkbox on the TestRunner resolved the problem.  The existence of this checkbox suggests that others have had this problem.

Thanks!
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10868933
8-)
0
 
LVL 92

Expert Comment

by:objects
ID: 10873144
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
This video teaches viewers about errors in exception handling.

947 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now