Solved

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

Posted on 2004-04-19
21
1,096 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
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
 
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

Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

Question has a verified solution.

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

Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
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…
Suggested Courses

631 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