Archive for February, 2006

In case you run into this issue …

Saturday, February 18th, 2006

While upgrading our WLS console to use the latest libraries i.e. to use the latest Struts, Beehive, WebLogic Portal versions. I ran into this problem that caught me completely off gaurd and took me a while to figure whats going on. Struts 1.2.7 distribution comes with commons logging 1.0.4 and log4j 1.2.8. Once I upgraded our console to struts 1.2.7 and tried to deploy it to the server the deployment failed with the error below.

java.lang.NoSuchMethodError: isEnabledFor
······at org.apache.commons.logging.impl.Log4JCategoryLog.isErrorEnabled(Log4JCategoryLog.java:189)
······at org.apache.beehive.netui.util.logging.Logger.isErrorEnabled(Logger.java:97)
······at org.apache.beehive.netui.pageflow.internal.AdapterManager.getServletContainerAdapter(AdapterManager.java:47)
······at org.apache.beehive.netui.pageflow.PageFlowUtils.createURLTemplatesFactory(PageFlowUtils.java:1716)

Well, initially I thought this is caused due to another version of commons-logging.jar lurking around somewhere in the system classpath and is being picked up by the application. But after carefully reviewing the classpath and other libraries in the application I did not find any foul play, this just drove me crazy. Thought I would instrument the Log4JCategoryLog class to see what methods it is seeing in “org.apache.log4j.Category” that is making it to fail with NSME. After compiling and re-packaging it in commons-logging.jar to my surprise everything worked as normal. I could see my debug output that I put in while instrumenting Log4jCategoryLog. At this point it made me think if the class file packaged in commons-logging.jar is erroneous. To prove that I had to isolate the problem to just commons-logging and log4j. Thanks to another colleague, this simple reproducer revealed the issue.

public class Foo {
···// Ensure that your classpath has commons-logging-1.0.4.jar and log4j-1.2.8.jar
···public static void main(String[] args) {
······org.apache.commons.logging.impl.Log4JCategoryLog x = new org.apache.commons.logging.impl.Log4JCategoryLog();
······x.isErrorEnabled();
···}
}

This simple client failed with the exact same error I was seeing while deploying the console. I believe the problem is the classes in commons-logging-1.0.4 that come from apache have been compiled with the wrong log4j Category class.
If you do javap -c org.apache.commons.logging.impl.Log4JCategoryLog with commons-logging-1.0.4.jar in classpath you will see that for isErrorEnabled method,

public boolean isErrorEnabled();
Code:
0: aload_0
1: getfield #7; //Field category:Lorg/apache/log4j/Category;
4: getstatic #14; //Field org/apache/log4j/Level.ERROR:Lorg/apache/log4j/Level;
7: invokevirtual #17; //Method org/apache/log4j/Category.isEnabledFor:(Lorg/apache/log4j/Level;)Z
10: ireturn

Here the log4j’s Category’s isEnabledFor takes Level as an argument, but Log4JCategoryLog is expecting an object of type Priority. If I re-compile Log4JCategoryLog and re-package it and do a javap -c on the class I get,

public boolean isErrorEnabled();
Code:
0: aload_0
1: getfield #2; //Field category:Lorg/apache/log4j/Category;
4: getstatic #9; //Field org/apache/log4j/Priority.ERROR:Lorg/apache/log4j/Priority;
7: invokevirtual #12; //Method org/apache/log4j/Category.isEnabledFor:(Lorg/apache/log4j/Priority;)Z
10: ireturn

As you see the log4j’s Category’s isEnabledFor method takes an object of type Priority as an argument which is right. After googling a little bit I found that this has been corrected with the new commons-logging jar available at http://www.ibiblio.org/maven/commons-logging/jars/commons-logging-1.1-dev.jar.

_uacct = “UA-2684269-2″;
urchinTracker();

Jython is just too useful

Wednesday, February 15th, 2006

Recently I had to do this repeatedly while working on a project.
1) Revert files with extension .foo that are checked out from source control under a base directory structure.
2) Sync to the latest copy of these files.
3) Make a copy of these files with extension .foo in a directory that are in different directories underneath this base directory to files with different extension .bar.
4) Delete the original file from source control.
5) Add the copied file to the source control.
This could have been achieved manually or using a shell/perl script. Manually it would have taken me a long time, since I am not very comfortable with a shell or a perl script, thought I would write this in jython. It took me 10 minutes to come up with this script, and while doing so I found an extremely useful module, shutil. The script can be massaged a bit to make it more efficient.
Here’s the script that I wrote.

import os
import shutil
# define the source control commands here
delete = “p4 delete “
add = “p4 add “
forceSync = “p4 sync -f “
revert = “p4 revert “

def dirwalk(dir):
···”’walk a directory tree”’
···for f in os.listdir(dir):
······fullpath = os.path.join(dir, f)
······print “Looking at “+fullpath
······if os.path.isdir(fullpath) and not os.path.islink(fullpath):
·········dirwalk(fullpath)
·········if os.path.isfile(fullpath):
············s = String(fullpath)
············work(s, fullpath)

def work(myStr, thePath):
···if myStr.endsWith(sys.argv[2]):
······# first revert
······theStr = String(revert)
······cStr = theStr.concat(myStr)
······Runtime.getRuntime().exec(cStr)
······# now force sync the file
······theStr = String(forceSync)
······cStr = theStr.concat(myStr)
······Runtime.getRuntime().exec(cStr)
······# now copy the file to a different extension
······_myStr = myStr.replaceAll(sys.argv[2],sys.argv[3])
······# copy the file to the new extension
······shutil.copy(myStr, _myStr)
······# now delete the file from source control
······theStr = String(delete)
······cStr = theStr.concat(myStr)
······Runtime.getRuntime().exec(cStr)
······# now add the new file
······theStr = String(add)
······cStr = theStr.concat(_myStr)
······Runtime.getRuntime().exec(cStr)

“”"
Usage:
java weblogic.WLST c:/scripts/p4files.py d:/myfiles .foo .bar
This will revert all files under myfiles directory from source control, force sync’s the files,
copy the file to the given extension, deletes the file from source control and add the new file
to source control
“”"
dirwalk(sys.argv[1])

As you can see Jython is not only useful to call into Java objects you can also use it to call into operating system for file manipulation and also use most of the python modules with utmost ease.
This is one of the many many uses of Jython.

_uacct = “UA-2684269-2″;
urchinTracker();