I user RSA 7.0.0.5
Since i use the fixpack 6.1.0.19 for websphere, no way to use the log4j implementation for commons-logging.
I have in /src two files :
*commons-logging.properties :*
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
*log4j.xml*
I use library such as hibernate or spring and before the fixpakc 6.1.0.19 all those library (who use commons-logging) log into separate files wich i specified in the log4j.xml. Now, the log goes directly into the console and nothing is logged in files anymore
I put the log configuration of log4j.xml to debug="true" and i see all the appender and logger are correctly configured.
I put a breakpoint in one of my class which use commons logging :
*private Log log = LogFactory.getLog(ProjetBlancPlugin.class);
log.debug("HELLO");*
and i can see that the implementation of the Log is : *com.ibm.ws.logging.WsLogger*
I would like this to be *org.apache.commons.logging.impl.Log4JLogger* (as specified in commons-loggin.properties)
My web module classloader strategy is PARENT_LAST.
I repeat this worked before fixpakc 6.1.0.19...
I anyone knows how to make it work again...
Thank you. Thieum.
I don't know which of those lines are really important...
I am having the commons-logging.properties with the following settings in the project within the source folders with the following settings.
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
priority=1
I also tried to put this file to the profile/properties folder.
Though nothing did work. The Server is instantiating WSLogger instead of Log4JLogger.
When I am running the same project artifact (ear) on another server, I do get a Log4JLogger :-0 So there must be something within the
server.
The EAR's Classloader settings are set to Parent_Last. I checked everything regarding the classloader (I guess) and as I already mentioned these
settings do word on a second Server. The only difference between those servers that I can see is that the Server where it works is a 6.1.0.7 and the
one where it does not is 6.1.0.17
Does anyone have an idea how I can solve this Problem
Thanks,
Alex
Alex,
Here is how we solved this problem:
commons-logging.properties is in the root of the WebContent folder in
RAD 7.0.0.7 (WAS 6.1.0.13)
log4j.properties is in WebContent/WEB-INF
In the WEB project's WebContent/META-INF (not WEB-INF) folder we
created a services folder
In the services folder we have a file named
org.apache.commons.logging.LogFactory
In the org.apache.commons.logging.LogFactory file we have the
following one line of text:
"org.apache.commons.logging.impl.Log4jFactory" (without the quotes)
Both the commons-logging jar and log4j jar are in the in Web Libraries
for the project which effectively places them in WEB-INF/lib (under
the covers)
We have a servlet in our web deployment descriptor that loads on
startup and uses the Log4j PropertyConfigurator class to initialize
log4j with the settings in the log4j.properties file mentioned above.
The rest of our classes can now use the commons logging Log and
LogFactory classes to log messages via log4j.
Some J2EE Guy
I wasn't using RSA though, and the problem appeared when testing the packaged EAR in WAS. Anyway, here's what I did:
- Create the following directory-structure in the archive (I did this in my WAR, I haven't tested this in the top-level EAR META-INF):
{code}/META-INF/services/{code}
- In /META-INF/services/, create a file named "org.apache.commons.logging.LogFactory"
- In this file, write down the logging implementation you wish to use, for example:
{code}org.apache.commons.logging.impl.Log4jFactory{code}
And that's it.
I read somewhere that this method isn't supported, but it worked for me.
It also has the added benefit of not having to fiddle around with the WAS configuration and classloaders.
Alvin.
see the section: "Choosing a LogFactory Implementation"
The overall issue here is the classloader. In WAS we have PARENT_FIRST and PARENT_LAST. Check your setting and what is allowed with your operations team.
When the classloader policy is set to PARENT_FIRST, please follow the instructions mentioned in the previous post to set the server definitions required to properly operate commons-logging and Log4j.
When the classloader policy is set to PARENT_LAST, an application may place an upgraded commons-logging JAR ahead of the base classes provided by WAS. For applications that are running with PARENT_LAST, a developer would need to setup the following -
1. Add the jar to the classpath of the project. For example, commons-logging-1.1.jar.
2. Add the log4j.properties or log4j.xml to the classpath of the project.
3. Make sure there is a commons-logging.properties file in the classpath of the project.
4. Make sure there is the following in the commons-logging.properties
priority=1
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
If you are using PARENT_LAST, don't go through all the hassle of server defs when you can solve it locally and not affect other applications on the server.
Kevin
Alvin, it turns out that this approach is supported, and is the preferred method for specifying an alternate LogFactory implementation.
The WAS InfoCenter suggests this approach as the best practice on this page:
[http://publib.boulder.ibm.com/infocenter/wasinfo/v6r1/topic/com.ibm.websphere.nd.multiplatform.doc/info/ae/ae/ttrb_classload_jcl.html]
Thanks for the good advice!
Andy
I still cannot get this to work. On 6.0.1.13 I had no problem with commons logging. I had a commons-logging.properties file with the following
priority=1
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
and no other configuration was needed. I used the default classloader of parent first and everything just worked with commons logging 1.1. Then when I upgraded to 6.1.0.17, logging no longer worked with that configuration.
So did something change in Websphere between these fix packs?
I've tried methods suggested above of adding the org.apache.commons.logging.LogFactory file to the META-INF/services directory but it doesn't seem to do the trick.
Any idea what else I'm missing to get commons logging working on 6.1.0.17? I would prefer not to have to modify the classloader or set up the shared libraries discussed above.
What is the best approach.
Thanks
Can you be more specific than 'cannot get this to work' ?
Ken
I found that:
* WAS bundles a "custom" version of Commons Logging that does not include all the classes included in Commons Logging distribution. After running some debugging I found that the distribution WAS bundles appears to be closest to 1.0.3, but WAS does not bundle all the 1.0.3 classes (notably it does not bundle "org.apache.commons.logging.impl.Log4JLogger" which is pretty important for Log4J to work)
* WAS also bundles a commons-logging.properties file which will be higher in the classloader than yours, so deploying one in your ear will make no difference if you use PARENT FIRST classloading.
* org.apache.commons.logging.impl.Log4JLogger was deprecated in commons logging 1.0.3 and removed in 1.1, so you _must_ deploy Commons Logging 1.0.x to use that logger.
Have a look through the blog for how I fixed it in my case.
I really wish IBM would change the package name for packaged open-source libraries (eg, com.ibm.org.apache.commons.logging). That would prevent these classloading conflicts.
Hope that helps,
Jason
http://majikshoe.blogspot.com/2009/01/joys-of-websphere-61-and-commons.html
If Jakarta Commons Logging (JCL) 1.0.3 is sufficient, then to get to Log4J, you must provide the Log4J jar in your app and then you can set up a file called org.apache.commons.logging.LogFactory in your META-INF/services directory with the content:
org.apache.commons.logging.impl.Log4JFactory
If you need a newer version of JCL and can change your application classLoader(s) to ParentLast, then put the Log4J and JCL jars in your app along with the commons-logging.properties in your app.
If you need a newer version of JCL and cannot use application classLoader(s) set to ParentLast, then move the JCL, Log4J, and commons-logging.properties to a directory. Set up a sharedLib to that directory, and set up a single classLoader to specify that sharedLib as its only class, and have that classLoader specify ParentLast.
The last option becomes a bit easier in WebSphere 7.0 with the introduction of isolated shared libraries which can be used at the app level instead of the server level. If you search back to the Word Doc or wait for the Support Authority column, you will see better details on this.
I found quite a simple solution for this problem, no shared library to add.
I found it after migrating one of my apps to WSFP (while on WAS 6.1, my JCL 1.1 problem was resolved with classloader on parent last,
I could not use anymore this solution with WSFP (see MikeC711 documentation [dwWriteUp.doc|http://www.ibm.com/developerworks/forums/servlet/JiveServlet/download/266-227753-14177279-334591/dwWriteUp.doc]).
I have filled a PMR, but no satisfying answer for the moment, hope IBM will publish an official solution for WSFP (you can also check for PMR 72352,122,000 as mentioned in the dwWriteUp.doc).
Anyway here is the solution (works for WAS 6.1, WSFP. Did not tested on WAS 7 but should work).
You will need to :
set application classLoader set to ParentLast.
download slf4j [http://www.slf4j.org/].
remove commons-logging.jar from your application.
add slf4j-api-1.5.8.jar
add jcl-over-slf4j-1.5.8.jar
if you want to use log4j, add slf4j-log4j12-1.5.8.jar and of course log4j-.jar.
if you want to use another logging system just add the appropriate slf4j jar.
Now you application can continue using JCL APIs while in fact it is using SLF4J implementation which bridges to Log4J or whatever logging system you want.
I've used it with Spring in my webapp and it works just fine.
Thanks to IBM support for the good article !
Thanks.
Simplest solution I've found is using slf4j (without any code change : just use JCL bridge) and PARENT_LAST. SLF4J setup is explained in this thread.
I don't remember if I had to use PARENT_LAST though
Extract from the article :
JCL V1.0.3
JCL routing through Log4J
If you prefer to use Log4J to handle the logging done with JCL 1.0.3, then some simple configuration is necessary:
1. Include the Log4J JAR and JCL 1.0.3 JAR in your application’s WEB-INF/lib directory.
2. Create a file called org.apache.commons.logging.LogFactory in your application’s META-INF/services directory.
This file contains just one line of text: org.apache.commons.logging.impl.Log4jFactory
Otherwise if you have pb with PARENT_LAST, just post your stacktrace, perhaps someone will know your pb and you'll be able to work with PARENT_LAST ?
If you have it in your ear or web-inf/lib, that's it.
But be cautious, perhaps you need the version you have in you app (WSFP QName class is for JAX-WS 2.0, while some ws engine use JAX-WS2.1 which use another version of QName class).
I have jax-rpc.jar in my web-inf/lib which has QName class , but that is needed by some classes in the application. Basically , this is what my app does:
It hosts some WS-I Compliant webservices , but also consumes third party webservices which are not ws-i compliant and hence the axis and jax-rpc jars in web-inf/lib. Also the application is using openJPA. Everyhting is working on 6.1.0.17 , no issues. On 6.1.0.19 , with default class loading(parent first) my application seems to find log4j without any issues , but when the OpenJPA tries to initialize persistence env. it complains that log4j.priority class is not found and fails to initialize . If i change the class loading policy to parent last ,i get the NoClass def on handler class.
Thanks for all your time.
[7/15/09 15:48:07:014 EDT] 0000002a PivotHandlerW E com.ibm.ws.webservices.engine.PivotHandlerWrapper bindExceptionToResponse WSWS3400I: Info: unexpected exception.
java.lang.NoClassDefFoundError: org.apache.log4j.Priority
at java.lang.J9VMInternals.verifyImpl(Native Method)
at java.lang.J9VMInternals.verify(J9VMInternals.java:68)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:129)
at org.apache.openjpa.lib.log.Log4JLogFactory.newLogAdapter(Log4JLogFactory.java:33)
at org.apache.openjpa.lib.log.LogFactoryAdapter.getLog(LogFactoryAdapter.java:40)
at org.apache.openjpa.lib.conf.ConfigurationImpl.getLog(ConfigurationImpl.java:225)
at org.apache.openjpa.conf.OpenJPAConfigurationImpl.getConfigurationLog(OpenJPAConfigurationImpl.java:1475)
at org.apache.openjpa.persistence.PersistenceProductDerivation$ConfigurationProviderImpl.setInto(PersistenceProductDerivation.java:426)
at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newInstance(JDBCBrokerFactory.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:79)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:618)
at org.apache.openjpa.kernel.Bootstrap.invokeFactory(Bootstrap.java:124)
at org.apache.openjpa.kernel.Bootstrap.newBrokerFactory(Bootstrap.java:62)
at org.apache.openjpa.persistence.PersistenceProviderImpl.createEntityManagerFactory(PersistenceProviderImpl.java:78)
at com.ibm.websphere.persistence.PersistenceProviderImpl.createEntityManagerFactory(PersistenceProviderImpl.java:64)
at com.ibm.websphere.persistence.PersistenceProviderImpl.createEntityManagerFactory(PersistenceProviderImpl.java:34)
at org.apache.openjpa.persistence.PersistenceProviderImpl.createEntityManagerFactory(PersistenceProviderImpl.java:87)
at org.apache.openjpa.persistence.PersistenceProviderImpl.createEntityManagerFactory(PersistenceProviderImpl.java:52)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)
at com.bcbssc.fastar.api.common.util.PersistenceUtil.getEntityManagerFactory(PersistenceUtil.java:46)
at com.bcbssc.fastar.api.common.util.TransactionUtil.(TransactionUtil.java:34)
at com.bcbssc.fastar.api.services.handlers.ProviderPaymentHandler.handleRequest(ProviderPaymentHandler.java:45)
at com.ibm.ws.webservices.engine.handlers.jaxrpc.HandlerProxy.handleRequest(HandlerProxy.java:145)
at com.ibm.ws.webservices.engine.handlers.jaxrpc.JAXRPCHandlerChain.handleRequest(JAXRPCHandlerChain.java:334)
at com.ibm.ws.webservices.engine.handlers.soap.SOAPHandlerChain.handleRequest(SOAPHandlerChain.java:176)
at com.ibm.ws.webservices.engine.handlers.jaxrpc.JAXRPCHandler.invokeServerRequestHandler(JAXRPCHandler.java:506)
at com.ibm.ws.webservices.engine.handlers.jaxrpc.JAXRPCSOAPHandler.invokeServerRequestHandler(JAXRPCSOAPHandler.java:184)
at com.ibm.ws.webservices.engine.handlers.jaxrpc.JAXRPCHandler$1.invoke(JAXRPCHandler.java:380)
at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:208)
at com.ibm.ws.webservices.engine.handlers.jaxrpc.JAXRPCHandler.invoke(JAXRPCHandler.java:152)
at com.ibm.ws.webservices.engine.handlers.WrappedHandler.invoke(WrappedHandler.java:64)
at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:228)
at com.ibm.ws.webservices.engine.PivotHandlerWrapper.invoke(PivotHandlerWrapper.java:228)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:402)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:347)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:83)
at java.lang.ClassLoader.loadClass(ClassLoader.java:597)
... 62 more
Thanks,
Interesting, didn't knew about that.
Since you really have classloading issues with PARENT_LAST, the only solution I see would be to use JCL 1.0.3 as described here http://www.ibm.com/developerworks/websphere/techjournal/0901_supauth/0901_supauth.html.
I've tested using this solution on 6.1.0.13 - it works.
But, someone told me that on WAS 6.1.0.23 (without WSFP) it doesn't work. So be catious ;)
Of course, if 6.1.0.25 works for you perhaps sticking on 6.1.0.25 would be the better option ;).
Anyone if someone knows what's the difference in JCL behaviour between all the WAS fixes, I would be very interested.
Thanks for your time .