Configuring CXF Logging To Go Through Log4J
Apparently, CXF has chosen the JSE logging API as their API against logging. But you can make CXF log through Log4J quite easily. In the org.apache.cxf.common.logging package of the CXF apidocs, I found the Log4JLogger class, which is a specialization of the JSE logging api java.util.logging.Logger class, delegating logging to a Log4J implementation.
Configuring Log4J in CXF
In the same package as Log4JLogger, I also found the LogUtils class, which CXF uses to obtain logger instances from. This class also contains a static final string KEY, which is set to the value org.apache.cxf.Logger. CXF uses this value, to bootstrap which logging API to use.
You can either put a META-INF/cxf/org.apache.cxf.Logger file onto the classpath with the org.apache.cxf.common.logging.Log4jLogger class name in it as a single line, or you can supply a -Dorg.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger system property to your code, when executing.
January 30, 2008
·
polesen ·
34 Comments
Tags: cxf, Java, log4j, logging · Posted in: Programming

34 Responses
Tech Per » Blog Archive » Viewing Inbound and Outbound Messages in CXF - January 30, 2008
[...] messages through its logging API. As a standard, the logging API in CXF is JDK logging, but you can configure CXF to use Log4J logging instead. You will need to ensure, that at least INFO level logging has been enabled for these [...]
Tech Per » Blog Archive » Making CXF Log RuntimeExceptions From Server Implementations - February 28, 2008
[...] mentioned in my post on how to configure log4j as logging engine in cxf, cxf comes out of the box with JavaSE logging (java.util.logging) as its logging engine. If you [...]
I can’t find META-INF/cxf/org.apache.cxf.Logger file in my CXF directory.
Any idea how can I achieve logging.
That is because you are supposed to supply that file yourself, instead of relying on the default.
Create the META-INF/cxf/org.apache.cxf.Logger file somewhere on your classpath. If you are building a war, for instance, it should end up in WEB-INF/classes/META-INF/cxf/org.apache.cxf.Logger (or inside a jar in WEB-INF/lib).
Really gr8! helped me to solve longing issues in CXF
I have created META-INF/cxf/org.apache.cxf.Logger file under WEB-INF/classes directory.
Satheesh
Great info. I’ve found that a simple
System.setProperty(“org.apache.cxf.Logger”, “org.apache.cxf.common.logging.Log4jLogger”);
before any CXF invocation, solves the problem for me.
Cheers!
Great, thanks a lot
put org.apache.cxf.Logger file under WEB-INF/classes/META-INF/cxf/ directory
Thanks for the tips Per (and everyone else). I’ve opted for the same approach Camilo is using. It *does* log a great deal of information, but the “raw” request/response is not recorded. What am I missing?
To log inbound and outbound messages you alse need to do what this post says logging inbound and outbound messages
where do we find the org.apache.cxf.Logger file. I am not having cxf directory in META-INF directory.
You are supposed to create that directory and file in it yourself. So,..
1. in your source code make a META-INF/cxf directory
2. create a file in that directory, specificly named “org.apache.cxf.Logger”
3. Write one single line in that file, with the content “org.apache.cxf.common.logging.Log4jLogger”
Make sure that your build process, being it ant, maven or something else, includes the META-INF/cxf catalogue in your compiled output (e.g., ensure it is included in your runtime classpath when your app executes somewhere).
Or, use the other approach of a system property, if that fits your needs better.
I have tried what you are suggesting (step 1 to 3) but no luck for me. Is there any additional jar file needed for this (I have log4j jar) or any other configuration in log4j.property file.
I tried with another method that is to use System property before the cxf invocation like
System.setProperty(“org.apache.cxf.Logger”, “org.apache.cxf.common.logging.Log4jLogger”);
This too does not work for me.
Please suggest me what I have to check.
@Saravanan:
Hmm, here’s a couple of things you could try
* if you would like some information from cxf, yes you should enable DEBUG or INFO or the like og org.apache.cxf package in log4j.properties
* if you are unsure if log4j config is read properly, try putting -Dlog4j.debug=true on the VM when starting your app, which should make log4j log to stdout when it is initializing and where it is loading log4j.properties from
* it seems like you can explicitly set the logger on CXF to the logging class you prefer, by doing “LogUtils.setLoggerClass(org.apache.cxf.common.logging.Log4jLogger.class)” (I haven’t tried this myself)
@polesen,
Thanks for your suggestions.
i tried with LogUtils.setLoggerClass(org.apache.cxf.common.logging.Log4jLogger.class and it works fine.
But it logs twice. I cant able to fix this.Any idea?Please help me to trigger out this issue.
@Saravanan:
“logs twice”.
Hmm. Strange. Could you provide a small sample of a couple of log statements as they appear when you see them twice?
@polesen
The extra log is due to I have configured Logging Interceptors in log4j.properties. Thanks for your continuous help. Finally it works fine. Thanks polesen.
Final clarification:
Now the logged Inbound and Outbound messages are printed in single line. Is there possible to log the messages as seperate lines.
@Saravanan: “…printed in single line”.
That is strange. Don’t know what happen there. The inbound and outbound messages are logged on two separately named loggers, so they should come as separate lines too.
FYI : CXF will also support logging through SLF4J in the forthcoming 2.2.8 version thanks to the org.apache.cxf.common.logging.Slf4jLogger .
Details are available on http://cxf.apache.org/docs/debugging-and-logging.html , paragraph “Using SLF4J Instead of java.util.logging (since 2.2.8)”.
Hope this helps,
Cyrille
Hi Guys
Thanks for the useful info. i tried the steps above but still cannot see the logging work. no one mentioned where to create the log4j property or xml file to specify the log file name and location. can some one advise pl….
regards
Paul Henderson
@Paul
The post as such is not about configuring log4j, but about if you already have log4j configured for your own system, how to make CXF log through that same configuration instead of JDK logger.
So, if your problems are related to log4j configuration itself, this post will not help you that much.
One tip though: A good place to start with log4j config debugging is starting your app with “-Dlog4j.debug=true”, as this will make it output how it initializes itself at bootstrap.
Hi Friends, ur post are really useful. I tried them and it works fine.
But I have a concern, It now logs all the activities…. is it possible to restrict it by any means.
–Thanks
Dharm
@Dharm: Don’t know about that. But I don’t think so.
Thanks polesen,
Let me eloborate my Question,
Now my logger is logging all the activities like
———————————————————
2010-06-22 10:30:23,243 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.HolderOutInterceptor@52a852a8
2010-06-22 10:30:23,243 DEBUG [WebContainer : 0] interceptors.HolderOutInterceptor – op: [OperationInfo: {http://services.vzw.com/}getReferenceData]
2010-06-22 10:30:23,243 DEBUG [WebContainer : 0] interceptors.HolderOutInterceptor – op.hasOutput(): true
2010-06-22 10:30:23,243 DEBUG [WebContainer : 0] interceptors.HolderOutInterceptor – op.getOutput().size(): 1
2010-06-22 10:30:23,243 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.SwAOutInterceptor@51fa51fa
2010-06-22 10:30:23,243 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor@52885288
2010-06-22 10:30:23,258 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.SoapHeaderOutFilterInterceptor@4d9c4d9c
2010-06-22 10:30:23,258 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor@4ef84ef8
2010-06-22 10:30:23,258 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.interceptor.MessageSenderInterceptor@4fee4fee
2010-06-22 10:30:23,258 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Adding interceptor org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor@50065006 to phase prepare-send-ending
2010-06-22 10:30:23,258 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Chain org.apache.cxf.phase.PhaseInterceptorChain@67b667b6 was modified. Current flow:
pre-logical [HolderOutInterceptor, SwAOutInterceptor, WrapperClassOutInterceptor, SoapHeaderOutFilterInterceptor]
post-logical [SoapPreProtocolOutInterceptor]
prepare-send [MessageSenderInterceptor]
pre-stream [LoggingOutInterceptor, AttachmentOutInterceptor, StaxOutInterceptor]
write [SoapOutInterceptor]
marshal [WrappedOutInterceptor, BareOutInterceptor]
prepare-send-ending [MessageSenderEndingInterceptor]
2010-06-22 10:30:23,258 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.interceptor.LoggingOutInterceptor@67ac67ac
2010-06-22 10:30:23,258 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.interceptor.AttachmentOutInterceptor@4d424d42
2010-06-22 10:30:23,258 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Invoking handleMessage on interceptor org.apache.cxf.interceptor.StaxOutInterceptor@4d784d78
2010-06-22 10:30:23,274 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Adding interceptor org.apache.cxf.interceptor.StaxOutInterceptor$StaxOutEndingInterceptor@47cc47cc to phase pre-stream-ending
2010-06-22 10:30:23,274 DEBUG [WebContainer : 0] phase.PhaseInterceptorChain – Chain org.apache.cxf.phase.PhaseInterceptorChain@67b667b6 was modified. Current flow:
pre-logical [HolderOutInterceptor, SwAOutInterceptor, WrapperClassOutInterceptor, SoapHeaderOutFilterInterceptor]
post-logical [SoapPreProtocolOutInterceptor]
prepare-send [MessageSenderInterceptor]
pre-stream [LoggingOutInterceptor, AttachmentOutInterceptor, StaxOutInterceptor]
write [SoapOutInterceptor]
marshal [WrappedOutInterceptor, BareOutInterceptor]
——————————————————-
Where as what we actually need is the inbound and outbound soap msg/fault….
is it possible by any means to stop this and log only required part.
Thanks
Dharm
Aaah, I see, yes. I think what you need is what I have described in this blogpost about outbound and inbound cxf logging.
It looks like, that you have turned on log4j debugging of all of cxf. For outbound and inbound logging, you need only turn debugging on for these two logger names:
org.apache.cxf.interceptor.LoggingInInterceptor
org.apache.cxf.interceptor.LoggingOutIntercepto
Thanks for the straight-forward and working logging configuration information! I now have some information to work with.
Regards,
Frank
Thanks polesen,
Your clarification in the comments
“Create the META-INF/cxf/org.apache.cxf.Logger file somewhere on your classpath. If you are building a war, for instance, it should end up in WEB-INF/classes/META-INF/cxf/org.apache.cxf.Logger (or inside a jar in WEB-INF/lib).”
Was just what I needed to get log4j and cxf playing together
can you post the content for org.apache.cxf.Logger for some default settings
I have followed the following steps and implemented accordingly.But if i want to change the log level where can i mention(eg: from debug to info) especially console log level during the server startup
1. in your source code make a META-INF/cxf directory
2. create a file in that directory, specificly named “org.apache.cxf.Logger”
3. Write one single line in that file, with the content “org.apache.cxf.common.logging.Log4jLogger”
Make sure that your build process, being it ant, maven or something else, includes the META-INF/cxf catalogue in your compiled output (e.g., ensure it is included in your runtime classpath when your app executes somewhere).
@Srinivas
Sorry for the late reply. For some reason I had not seen (or maybe forgotten about) your comment, so I first got around to moderating it now.
The file “org.apache.cxf.Logger” should ONLY contain the one line “org.apache.cxf.common.logging.Log4jLogger” to enable log4j logging. Actually configuring log4j log levels etc., you need to look to the log4j project to learn about.
Log4j both have a .properties config file format and a xml config file format you can use. I’ve always used the xml config file. You can also configure it programmatically.
If you place a file “log4j.xml” in the root of your classpath, log4j will automatically find and load that one.
You can also place it outside classpath, and provide the system property “-Dlog4j.configuration=file://….path to your file”.
If for some some reason you have trouble making log4j find and load your config, try setting “-Dlog4j.debug=true” on cmdline, at it will tell a whole lot about its bootstrapping/config loading.
See also: http://logging.apache.org/log4j/1.2/manual.html
@polesen
this post is veeery misleading. other people write posts to explain it (see http://www.thecorneroffice.org/blog/plink/2008/05/080501-2354.html ). it would be great if you provide a bit more clarification
@piotrek What..I don’t get it
, what is the misleading part? I can see from the post you are linking to, that when he actually did what the post says, it works
Suggestions for clarifications are welcome though
Polesen, I have another question — when I log cxf using the In and Out interceptors, it seems to log it OK, but I am interested in getting the round trip time.. from the point CXF receives a SOAP request to the point where CXF returns the SOAP response. Is it possible to map this info and integrate it with our webservices logs??
07:25:03,845 – INFO Inbound Message
—————————-
ID: 1
Address:
Encoding:
Content-Type:
Headers:
Payload: <soap:Envelope………..
<soap continued…
<soap continued…
<soap continued…
07:25:04,920 – DEBUG Invoking HTTP method POST
07:25:04,920 – DEBUG URIMappingInterceptor can only handle HTTP GET, not HTTP POST
07:25:05,021 – DEBUG Entering my app for acct: 1234
…
…
…
07:25:10,004 – DEBUG Exiting my app for acct: 1234 – Elapsed time: 4986 ms.
07:25:10,010 – DEBUG Interceptors contributed by bus: [org.apache.cxf.interceptor.LoggingOutInterceptor@5522a7b5]
07:25:10,011 – DEBUG Interceptors contributed by service: []
07:25:10,011 – DEBUG Interceptors contributed by endpoint: [org.apache.cxf.interceptor.MessageSenderInterceptor@563087bd, org.apache.cxf.jaxws.interceptors.SwAOutInterceptor@c1fb580, org.apache.cxf.jaxws.handler.logical.LogicalHandlerOutInterceptor@75c4ecb7, org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor@53911ec8, org.apache.cxf.jaxws.interceptors.HolderOutInterceptor@5c7c0754, org.apache.cxf.jaxws.handler.soap.SOAPHandlerInterceptor@52c54b3b]
07:25:10,011 – DEBUG Interceptors contributed by binding: [org.apache.cxf.interceptor.AttachmentOutInterceptor@16ce38f1, org.apache.cxf.interceptor.StaxOutInterceptor@3cfc61e9, org.apache.cxf.binding.soap.interceptor.SoapHeaderOutFilterInterceptor@5d802746, org.apache.cxf.interceptor.WrappedOutInterceptor@892949f, org.apache.cxf.interceptor.BareOutInterceptor@4f5b571e, org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor@75b49b45, org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor@243e0b62]
07:25:10,695 – INFO Outbound Message
As you can see above, actual time taken from A-Z (CXF entry to CXF exit) is:
07:25:03,845 —- to —- 07:25:10,695
However, i was able to capture only the time between:
07:25:05,021 —- to —- 07:25:10,004
This is misleading ‘cus I am only able to capture times within my app and not able to extend it to CXF.
Is there any way I can customize these interceptors to log the info the way I want?
Don’t know if you can get anything from CXF. Probably the easiest way for you to do this would be to create a servlet filter, and mount it in front of the CXF servlet. You could then log before chaining and after return from chain.
If you want the complete request timed, you should simply use your access_log of the server you are using, which most certainly can log millis/seconds pr. request.
Another way, that I’ve been using, it a combination of a servlet filter and the perf4j library. In the servlet filter, I extracted the SOAP method name from the request and then logged through perf4j with SOAP method name as tag. That, in combination with perf4j’s grouped timing statistics gives a great, realtime picture of ws request traffic on each ws method.
Thanks so much for this! We’re using SLF4J, which CXF now supports. Adding a META-INF file as you suggested with the following worked like a charm for me:
org.apache.cxf.common.logging.Slf4jLogger
Leave a Reply