Topic
16 replies Latest Post - ‏2012-02-17T18:55:43Z by tejuvenkat
middleware_analyst
middleware_analyst
15 Posts
ACCEPTED ANSWER

Pinned topic Log4j & WebSphere 6 is it possible at all without parent_last class loading

‏2008-02-07T04:58:43Z |
Hi,

I've read various articles on how log4j can be used with WebSphere using Commons logging.
The main two were:
http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.zseries.doc/info/zseries/ae/ctrb_classload_jcl.html
See the page called:
Configurations for the WebSphere Application Server logger

And:
http://wiki.apache.org/jakarta-commons/Logging/FrequentlyAskedQuestions
On the section:
How Can I Use Log4j with Commons-Logging 1.1 on WebSphere 6.0?

I attempted using Parent_last class loading but this failed and caused the entire application to fall apart.
It couldn't find classes it needed et cetera.

The jar's for commons-logging and log4j are in the classpath of the application, in WEB-INF/lib/ of the war file.

I tried playing with:
META-INF/services/org.apache.commons.logging.LogFactory

Although I am not sure what needs to go in here, I mean I want to use the jakarta commons logging factory to use the Log4j logger, org.apache.log4j.Logger

I tried doing some tricks like adding the priority flag and replacing the above file with contents like:
org.apache.commons.logging.Log=org.apache.log4j.Logger

And just the line "org.apache.log4j.Logger"

I also tried a few other combinations before giving up, I have no idea whats wrong.
What do I need to do to get log4j working on WebSphere 6?

Regards,
Gareth
Updated on 2012-02-17T18:55:43Z at 2012-02-17T18:55:43Z by tejuvenkat
  • middleware_analyst
    middleware_analyst
    15 Posts
    ACCEPTED ANSWER

    Re: Log4j & WebSphere 6 is it possible at all without parent_last class loa

    ‏2008-02-07T05:03:02Z  in response to middleware_analyst
    Also tried this one in the classes directory of the War file inside the ear (/X/WEB-INF/commons-logging.properties):
    priority=2
    org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
    org.apache.commons.logging.Log=org.apache.log4j.Logger
  • SystemAdmin
    SystemAdmin
    37422 Posts
    ACCEPTED ANSWER

    Re: Log4j & WebSphere 6 is it possible at all without parent_last class loading

    ‏2008-02-07T15:07:41Z  in response to middleware_analyst
    midrange.middleware@ge.com wrote:
    Hi,

    I've read various articles on how log4j can be used with WebSphere using Commons logging.
    The main two were:
    http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.zseries.doc/info/zseries/ae/ctrb_classload_jcl.html
    See the page called:
    Configurations for the WebSphere Application Server logger

    And:
    http://wiki.apache.org/jakarta-commons/Logging/FrequentlyAskedQuestions
    On the section:
    How Can I Use Log4j with Commons-Logging 1.1 on WebSphere 6.0?

    I attempted using Parent_last class loading but this failed and caused the entire application to fall apart.
    It couldn't find classes it needed et cetera.

    The jar's for commons-logging and log4j are in the classpath of the application, in WEB-INF/lib/ of the war file.

    I tried playing with:
    META-INF/services/org.apache.commons.logging.LogFactory

    Although I am not sure what needs to go in here, I mean I want to use the jakarta commons logging factory to use the Log4j logger, org.apache.log4j.Logger

    I tried doing some tricks like adding the priority flag and replacing the above file with contents like:
    org.apache.commons.logging.Log=org.apache.log4j.Logger

    And just the line "org.apache.log4j.Logger"

    I also tried a few other combinations before giving up, I have no idea whats wrong.
    What do I need to do to get log4j working on WebSphere 6?

    Regards,
    Gareth

    The META-INF/services approach has been working for us for years on many
    different versions of WAS. (We're on 6.1 now) You don't need (or likely
    want) to change the classloader ordering policy.

    Just make the contents of that file:

    org.apache.commons.logging.impl.Log4jFactory

    A couple references:

    http://www-1.ibm.com/support/docview.wss?uid=swg27010153

    And this:

    <http://groups.google.com/group/ibm.software.websphere.application-server/browse_thread/thread/dff0321c9bbbcb26/9bcfb553b265c33b?lnk=gst&q=log4j+doug#9b cfb553b265c33b>

    Doug
    • middleware_analyst
      middleware_analyst
      15 Posts
      ACCEPTED ANSWER

      Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

      ‏2008-02-07T23:37:40Z  in response to SystemAdmin
      "The META-INF/services approach has been working for us for years on many
      different versions of WAS. (We're on 6.1 now) You don't need (or likely
      want) to change the classloader ordering policy.

      Just make the contents of that file:

      org.apache.commons.logging.impl.Log4jFactory"

      Ok, I still can't get this working. Where should that file be going?
      Originally I thought it was in the META-INF/services of the WAR file, then I read:

      "
      A couple references:

      http://www-1.ibm.com/support/docview.wss?uid=swg27010153"

      And thought I'd need to re-package the commons-logging jar file with that file in the META-INF/services section.
      Neither actually worked.
      In fact, in that reference you supplied it always says to make the class loader parent last.

      I can't access google groups from work unless you want to paste in the results here :)

      So where am I going wrong? I clearly have something I'm doing that could be quite fundamentally wrong, I'm very used to the way Tomcat does things...
      Regards,
      Gareth

      Message was edited by: middleware_analyst
      Updated on 2008-02-07T23:37:40Z at 2008-02-07T23:37:40Z by middleware_analyst
      • SystemAdmin
        SystemAdmin
        37422 Posts
        ACCEPTED ANSWER

        Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

        ‏2008-02-08T14:45:35Z  in response to middleware_analyst
        midrange.middleware@ge.com wrote:
        "The META-INF/services approach has been working for us for years on many
        different versions of WAS. (We're on 6.1 now) You don't need (or likely
        want) to change the classloader ordering policy.

        Just make the contents of that file:

        org.apache.commons.logging.impl.Log4jFactory"

        Ok, I still can't get this working. Where should that file be going?
        Originally I thought it was in the META-INF/services of the WAR file, then I read:

        "
        A couple references:

        http://www-1.ibm.com/support/docview.wss?uid=swg27010153"

        And thought I'd need to re-package the commons-logging file with that file in the META-INF/services of that package.
        Neither actually worked.
        In fact, in that reference you supplied it always says to make the class loader parent last.

        I can't access google groups from work unless you want to paste in the results here :)

        Regards,
        Gareth

        Not sure what to tell you. We deploy inside our WAR file

        META-INF/services/org.apache.commons.logging.LogFactory

        whose contents are simply

        org.apache.commons.logging.impl.Log4jFactory

        And all the commons-logging that is done by any components in that web
        application is now controlled by our log4j.properties also deployed inside the
        WAR.

        This has been on WebSphere 5.0 and 6.1, at least, with log4j 1.2.x.

        The fact that you don't even get an error with a nonsense class in there seems
        to suggest to me that the file may not be where it needs to be, or may perhaps
        have a typo in the name? Just guessing here. Perhaps you can attach a list
        of the contents of the WAR file. The mechanism does work, so there must be
        something misconfigured somewhere.

        (The Google Groups reference is just to a discussion thread years ago where I
        first found this approach. Page 7 of the PDF lists this approach as well.
        Again, with this approach we do not have to change the classloader policy from
        PARENT_FIRST.

        I admit I hadn't read through the whole PDF - I found that one when I was
        seeking a different link, which now appears to be gone. Again, page 7 was
        just what I had specifically found to confirm the general approach. Where the
        PDF discusses PARENT_LAST is in the context of creating your own
        commons-logging.jar. If you want to use your own version, or just a different
        version than what comes with WAS, you'd have to use PARENT_LAST. I doubt
        there's any reason you'd need to do so, though, and that will open up other
        potential problems if you do.)

        Doug
        • middleware_analyst
          middleware_analyst
          15 Posts
          ACCEPTED ANSWER

          Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

          ‏2008-02-09T02:13:36Z  in response to SystemAdmin
          Hi Doug,

          I'm going to do a little re-arranging so I can reply to your comments:
          "I admit I hadn't read through the whole PDF - I found that one when I was
          seeking a different link, which now appears to be gone. Again, page 7 was
          just what I had specifically found to confirm the general approach. Where the
          PDF discusses PARENT_LAST is in the context of creating your own
          commons-logging.jar."

          Ok sure, I will re-read the PDF as the powerpoint presentation I read seemed to imply that you needed PARENT_LAST.

          "Not sure what to tell you. We deploy inside our WAR file
          META-INF/services/org.apache.commons.logging.LogFactory
          whose contents are simply

          org.apache.commons.logging.impl.Log4jFactory

          And all the commons-logging that is done by any components in that web
          application is now controlled by our log4j.properties also deployed inside the
          WAR.
          "
          "The fact that you don't even get an error with a nonsense class in there seems
          to suggest to me that the file may not be where it needs to be, or may perhaps
          have a typo in the name? Just guessing here. Perhaps you can attach a list
          of the contents of the WAR file. The mechanism does work, so there must be
          something misconfigured somewhere."

          I think I've found out whats going wrong now, the log4j.properties file was NOT getting found at all, this is likely because the EAR file had a commons-logging file.
          I am struggling with the way the classloader works, so please correct me at any point, but from what I understand, the EJB class loader would find the commons-logging, when the application looked for the commons-logging classes it would say "don't worry, its in memory".

          So, what I needed to do was move the log4j jar file from the WAR to the EAR level.
          I then added the commons-logging jar file to the class path of the MANIFEST.MF (this was required if PARENT_LAST loading is to work), I then switched to PARENT_LAST class loading at the WAR level only (this does not break the application), so it actually finds my log4j.properties file. Without PARENT_LAST it does not work as expected.

          When I get back to work on Monday, I will check if there is a good reason to have commons-logging at the EAR level, if NOT then I will move it to the WAR level only and use the META-INF/services/... example you have given to see if it works.

          Please note that I did try the META-INF/services example at the EAR level with the commons-logging file there, that did not work before either.

          So its working but now I need to spend some more time working out why and how I should have done it in the first place.

          Please note I did not create the application myself and I am reading a few articles on class loading to try and better understand how I can not fall into this problem again.

          Thanks a lot for your help and patience.

          Regards,
          Gareth
          • middleware_analyst
            middleware_analyst
            15 Posts
            ACCEPTED ANSWER

            Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

            ‏2008-02-11T06:13:44Z  in response to middleware_analyst
            Hi,

            Ok so we redeployed the app and my log4j logging simply stopped working, I did a bunch of tests and this was the ONLY way I could get it working:

            EAR file:
            commons-logging.jar
            log4j-1.2.12.jar

            WAR file:
            No commons-logging and no log4j files anymore.

            WAR MANIFEST.MF
            Manifest-Version: 1.0
            Class-Path: X.jar commons-logging.jar log4j-1.2.12.jar

            Create the META-INF/services/org.apache.commons.logging.LogFactory
            (yes I know I said it worked before, and I just can't get it working without this).

            AND change the class loader of the WAR to PARENT_LAST.

            I tried with the class loader of the WAR as PARENT_FIRST it did not work, I switched it back to PARENT_LAST, it works fine.
            So the above it one way (or the only way at the moment) that I can get my particular application logging to log4j VIA the commons-log interface. Logging directly to log4j may be easier but its cheating (and not best practice) :P

            Any comments on the above?
            All the help I received was appreciated.

            Regards,
            Gareth
            • SystemAdmin
              SystemAdmin
              37422 Posts
              ACCEPTED ANSWER

              Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

              ‏2008-02-11T15:55:01Z  in response to middleware_analyst
              midrange.middleware@ge.com wrote:
              Hi,

              Ok so we redeployed the app and my log4j logging simply stopped working, I did a bunch of tests and this was the ONLY way I could get it working:

              EAR file:
              commons-logging.jar
              log4j-1.2.12.jar

              WAR file:
              No commons-logging and no log4j files anymore.

              WAR MANIFEST.MF
              Manifest-Version: 1.0
              Class-Path: X.jar commons-logging.jar log4j-1.2.12.jar

              Create the META-INF/services/org.apache.commons.logging.LogFactory
              (yes I know I said it worked before, and I just can't get it working without this).

              AND change the class loader of the WAR to PARENT_LAST.

              I tried with the class loader of the WAR as PARENT_FIRST it did not work, I switched it back to PARENT_LAST, it works fine.
              So the above it one way (or the only way at the moment) that I can get my particular application logging to log4j VIA the commons-log interface. Logging directly to log4j may be easier but its cheating (and not best practice) :P

              Any comments on the above?
              All the help I received was appreciated.

              Regards,
              Gareth

              The classloader stuff definitely takes some thinking to properly understand.
              I always have to re-read about it when I'm trying to address a specific situation.

              So let's just start with a few specifics which I can recall from memory.

              1. WAS includes a copy of commons-logging (JCL), so you really shouldn't need
              to deploy that at all.
              2. Unless you switch to PARENT_LAST. In that configuration, your log4j
              wouldn't be able to see WAS' JCL. At least, I think that's the case.

              So it may be that simply removing JCL from your deploy will remove the need
              for PARENT_LAST. I don't know if you've tried that particular combination before.

              The exact configuration that works for us is this:
              1. deploy META-INF/services file inside the WAR file
              2. deploy log4j.jar inside the WAR file
              3. do not deploy commons-logging at all

              We have not tried to use any deploys to the EAR file/directory, and we have
              not set any WAS system libraries. (Coincidentally, however, one of our team
              members just recommended that we start exploring WAS shared libraries to
              reduce memory footprint, so we'll be be doing that soon.)
              Doug
              • middleware_analyst
                middleware_analyst
                15 Posts
                ACCEPTED ANSWER

                Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

                ‏2008-02-13T05:40:58Z  in response to SystemAdmin
                Hi Doug,
                "So let's just start with a few specifics which I can recall from memory.

                1. WAS includes a copy of commons-logging (JCL), so you really shouldn't need
                to deploy that at all.
                2. Unless you switch to PARENT_LAST. In that configuration, your log4j
                wouldn't be able to see WAS' JCL. At least, I think that's the case."

                I disagree here, PARENT_FIRST means that the highest level class loader will be called and then it will work downward, so it should find the WAS JCL from the library directory.

                "
                So it may be that simply removing JCL from your deploy will remove the need
                for PARENT_LAST. I don't know if you've tried that particular combination before.
                "

                On my particular EAR/WAR configuration, with my particular version of commons-logging this did not work.

                "The exact configuration that works for us is this:
                1. deploy META-INF/services file inside the WAR file
                2. deploy log4j.jar inside the WAR file
                3. do not deploy commons-logging at all"
                "

                Interesting, thanks for the information, I will be interested to see if the other applications can have the same technique used with the same results or not.
                I've searched the internet and found a huge amount of confusion on the subject, many thanks for your assistance here.

                Regards,
                Gareth
                • SystemAdmin
                  SystemAdmin
                  37422 Posts
                  ACCEPTED ANSWER

                  Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

                  ‏2009-05-22T12:40:43Z  in response to middleware_analyst
                  I encountered similar issues using commons-logging, Log4j and WebSphere 6.1 and believe I have a good solution for anyone having problems

                  The problem:
                  I have a J2EE application that uses third party jars (Spring) that use commons-logging. My own code also uses the commons-logging api to record debug messages.I want to configure my application to output the debug messages to the console when deployed to WebSphere.

                  My Investigation:
                  The root of the problem is that the commons-logging api is part of the WebSphere runtime com.ibm.ws.runtime_6.1.0.jar) and this is configured to use JDK14 logging to output messages. Inspecting the com.ibm.ws.runtime_6.1.0.jar the dates on the commons-logging classes are 7th April 2003 which correspond to the dates on the classes in commons-logging v1.0.3 that I downloaded from Apache. The other thing to note about the com.ibm.ws.runtime_6.1.0.jar is that not every commons-logging class is included. Importantly, the classes that hook commons-logging into Log4J are missing. This is why people are including the commons-logging.jar in their application and subsequently run into classloader issues because they have duplicate classes on the classpath and perhaps also different versions of these classes.

                  _Note to IBM: Do not add the missing commons-logging classes to com.ibm.ws.runtime_6.1.0.jar as this would only make the problem worse._

                  My Solution:
                  Download commons-logging v1.0.3 from Apache and unzip into a folder. Open the commons-logging.jar and remove from it all the classes that are already in com.ibm.ws.runtime_6.1.0.jar. You should then be left with the following 4 classes:
                  Log4JcategoryLog
                  Log4jfactory
                  Log4JLogger
                  LogKitLogger
                  You can now add this stripped down version of commons-logging.jar to your application and this will provide the classes you need to redirect logging to Log4j.
                  To redirect logging to log4j you first need to add log4j onto your application classpath and the latest jar (log4j-1.2.15.jar) will work fine.
                  Next you need to add configuration to redirect commons-logging to Log4j.
                  Add a file called commons-logging.properties to your applications with the following content:
                  priority=1
                  org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
                  org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

                  This file should be in the root of your source folder. In the same location you can put your log4j.properties file.
                  In my Rational/Eclipse IDE I created a Java project to holde these files and include the project in my application.
                  I believe that this is all that's required for a Java application.
                  For J2EE applications additional configuration is required.
                  Every WAR and EJB Jar file must contain a file named org.apache.commons.logging.LogFactory in META-INF/services
                  The contents of this file must read:
                  org.apache.commons.logging.impl.Log4jFactory

                  My WAR and EJB jar file also refer to my jar that contains commons-logging.properties and log4j.properties (I suspect access to commons-logging .propertes may not be required but I haven't confirmed this)

                  You should now be able to deploy your application to WebSphere and see messages in the console that are controlled by your log4j.properties file.

                  This solution has been tested on WebSphere Process Server v6.2 (based on WAS 6.1.0.23) and appears to work well.
                  It also works regardless of whether you use PARENT_FIRST or PARENT_LAST classloading.

                  Hope this helps.

                  Steve.
                  • SystemAdmin
                    SystemAdmin
                    37422 Posts
                    ACCEPTED ANSWER

                    Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

                    ‏2010-05-05T12:40:43Z  in response to SystemAdmin
                    It also solve the problem on a Websphere Application Server Express 6.1.0.29 here.
                    Great workaround, thank you !
                  • sasikiran_malladi
                    sasikiran_malladi
                    1 Post
                    ACCEPTED ANSWER

                    Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

                    ‏2011-05-19T14:26:27Z  in response to SystemAdmin
                    Excellent work around Steve !

                    Really saved my valuable time.

                    This worked in WPS 6.2 perfectly.
                    • PaulWeihs
                      PaulWeihs
                      1 Post
                      ACCEPTED ANSWER

                      Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

                      ‏2011-06-16T17:25:09Z  in response to sasikiran_malladi
                      Worked great for me in WebSphere 7. Thank you!
                  • tejuvenkat
                    tejuvenkat
                    1 Post
                    ACCEPTED ANSWER

                    Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last

                    ‏2012-02-17T18:55:43Z  in response to SystemAdmin
                    Thanks Steve. i tried this and it worked for WAS 7 also.
  • SystemAdmin
    SystemAdmin
    37422 Posts
    ACCEPTED ANSWER

    Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last class loa

    ‏2008-02-07T15:09:46Z  in response to middleware_analyst
    Hi Gareth,
    Have you tried just that one line:
    org.apache.commons.logging.impl.Log4jFactory

    in META-INF/services/org.apache.commons.logging.LogFactory?
    /s.
    • middleware_analyst
      middleware_analyst
      15 Posts
      ACCEPTED ANSWER

      Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last class loa

      ‏2008-02-08T04:23:59Z  in response to SystemAdmin
      Hi,

      slecallonnec wrote:
      Hi Gareth,
      Have you tried just that one line:
      org.apache.commons.logging.impl.Log4jFactory

      in META-INF/services/org.apache.commons.logging.LogFactory?
      /s.

      I tried that, I also tried setting it to classes that don't exist with the idea that WebSphere would throw some exceptions, nothing at all.
      I'm finding it frustrating to log to the Jakarta commons logging level, other suggestions on the net advised they put log4j properties file's in shared libraries and similar tricks.
      However I'd rather not do that.

      Others have also been logging to log4j directly, we are logging via commons logging.

      Regards,
      Gareth
      • SystemAdmin
        SystemAdmin
        37422 Posts
        ACCEPTED ANSWER

        Re: Log4j &#38; WebSphere 6 is it possible at all without parent_last class loa

        ‏2008-02-08T11:36:00Z  in response to middleware_analyst
        Hi Gareth,

        The best resource I ever found on that subject was the following document (actually strange I can't find it anywhere on the ibm website):

        http://mattfleming.com/files/active/0/ibm.pdf
        which was written for 5.x in mind, but I have used it for 6.x as well.

        It says in particular:

        "Specify the desired LogFactory implementation in the LogFactory file.
        a. Create a file named “org.apache.commons.logging.LogFactory”.
        b. Insert into it the name of the JCL LogFactory implementation class, without quotes!"

        And like Doug, it's always been working for me.

        Regards,
        /s.