Reputation: 32331
I am using the Apache CXF Framework. Inside my client program, I need to log CXF SOAP Requests and SOAP Responses. When I used
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setAddress(host);
factory.setServiceClass(MyService.class);
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
I got these SOAP Request and SOAP Responses in the console:
Nov 9, 2011 6:48:01 PM org.apache.cxf.interceptor.LoggingOutInterceptor$LoggingCallback onClose
INFO: Outbound Message
---------------------------
ID: 2
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns4:MYResponse
--------------------------------------
But my actual requirement is, instead of printing them to the server console, I need to have them inside the log file.
When I used log4j directly as shown
log4j(factory.getInInterceptors().add(new LoggingInInterceptor()));
log4j(factory.getOutInterceptors().add(new LoggingOutInterceptor()));
It is only printing true
and true
inside the log file.
Could anybody please let me know how to configure this?
Upvotes: 54
Views: 164103
Reputation: 876
Old configuration options will not work for those who use Apache CXF version 3.1 or later. Check here. In my case, I used apache cxf 3.4.2 in spring boot (version 2.4.2) project.
To print logging properly, you need to add feature in your Bus
object (in my case, it was SpringBus
) like following -
LoggingFeature
-LoggingFeature loggingFeature = new LoggingFeature();
loggingFeature.setPrettyLogging(true);
bus.setFeatures(Arrays.asList(loggingFeature));
In case if you need to check how will create bus in spring boot project, please check here.
Upvotes: 1
Reputation: 189
Procedure for global setting of client/server logging of SOAP/REST requests/ responses with log4j
logger.
This way you set up logging for the whole application without having to change the code, war, jar files, etc.
install file cxf-rt-features-logging-X.Y.Z.jar
to your CLASS_PATH
create file (path for example: /opt/cxf/cxf-logging.xml
):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<cxf:bus>
<cxf:features>
<bean class="org.apache.cxf.ext.logging.LoggingFeature">
<property name="prettyLogging" value="true"/>
</bean>
</cxf:features>
</cxf:bus>
</beans>
set logging for org.apache.cxf
(log4j 1.x) log4j.logger.org.apache.cxf=INFO,YOUR_APPENDER
set these properties on java start-up
java ... -Dcxf.config.file.url=file:///opt/cxf/cxf-logging.xml -Dorg.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true -Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true -Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true -Dcom.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true ...
I don't know why, but it is necessary to set variables as well com.sun.xml.*
Upvotes: 3
Reputation: 341003
You need to create a file named org.apache.cxf.Logger
(that is: org.apache.cxf
file with Logger
extension) under /META-INF/cxf/
with the following contents:
org.apache.cxf.common.logging.Log4jLogger
Reference: Using Log4j Instead of java.util.logging.
Also if you replace standard:
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
with much more verbose:
<bean id="abstractLoggingInterceptor" abstract="true">
<property name="prettyLogging" value="true"/>
</bean>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" parent="abstractLoggingInterceptor"/>
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" parent="abstractLoggingInterceptor"/>
<cxf:bus>
<cxf:inInterceptors>
<ref bean="loggingInInterceptor"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="loggingOutInterceptor"/>
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<ref bean="loggingOutInterceptor"/>
</cxf:outFaultInterceptors>
<cxf:inFaultInterceptors>
<ref bean="loggingInInterceptor"/>
</cxf:inFaultInterceptors>
</cxf:bus>
Apache CXF will pretty print XML messages formatting them with proper indentation and line breaks. Very useful. More about it here.
Upvotes: 77
Reputation: 2374
This worked for me.
Setup log4j as normal. Then use this code:
// LOGGING
LoggingOutInterceptor loi = new LoggingOutInterceptor();
loi.setPrettyLogging(true);
LoggingInInterceptor lii = new LoggingInInterceptor();
lii.setPrettyLogging(true);
org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(isalesService);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
cxfEndpoint.getOutInterceptors().add(loi);
cxfEndpoint.getInInterceptors().add(lii);
Upvotes: 6
Reputation: 135
In case somebody wants to do this, using Play Framework (and using LogBack http://logback.qos.ch/), then you can configure the application-logger.xml with this line:
<logger name="org.apache.cxf" level="DEBUG"/>
For me, it did the trick ;)
Upvotes: 2
Reputation: 11
cxf.xml
<cxf:bus>
<cxf:ininterceptors>
<ref bean="loggingInInterceptor" />
</cxf:ininterceptors>
<cxf:outinterceptors>
<ref bean="logOutInterceptor" />
</cxf:outinterceptors>
</cxf:bus>
org.apache.cxf.Logger
org.apache.cxf.common.logging.Log4jLogger
Please check screenshot here
Upvotes: 1
Reputation: 141
Simplest way to achieve pretty logging in Preethi Jain szenario:
LoggingInInterceptor loggingInInterceptor = new LoggingInInterceptor();
loggingInInterceptor.setPrettyLogging(true);
LoggingOutInterceptor loggingOutInterceptor = new LoggingOutInterceptor();
loggingOutInterceptor.setPrettyLogging(true);
factory.getInInterceptors().add(loggingInInterceptor);
factory.getOutInterceptors().add(loggingOutInterceptor);
Upvotes: 14
Reputation: 11
Try this code:
EndpointImpl impl = (EndpointImpl)Endpoint.publish(address, implementor);
impl.getServer().getEndpoint().getInInterceptors().add(new LoggingInInterceptor());
impl.getServer().getEndpoint().getOutInterceptors().add(new LoggingOutInterceptor());
Inside the logback.xml
you need to put the interface name for webservice:
<appender name="FILE" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator
class="com.progressoft.ecc.integration.logging.ThreadNameDiscriminator">
<key>threadName</key>
<defaultValue>unknown</defaultValue>
</discriminator>
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>logger.contains("InterfaceWebServiceSoap")</expression>
</evaluator>
<OnMismatch>DENY</OnMismatch>
<OnMatch>NEUTRAL</OnMatch>
</filter>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>TRACE</level>
</filter>
<sift>
<appender name="FILE-${threadName}"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOGGING_PATH}/${threadName}.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${ARCHIVING_PATH}/%d{yyyy-MM-dd}.${threadName}%i.log.zip
</FileNamePattern>
<MaxHistory>30</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>50MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%date{dd-MM-yyyy HH:mm:ss.SSS} | %5level | %-60([%logger{53}:%line]): %msg %ex{full} %n</Pattern>
</encoder>
</appender>
</sift>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="FILE" />
</root>
Upvotes: 1
Reputation: 2070
Another easy way is to set the logger like this- ensure that you do it before you load the cxf web service related classes. You can use it in some static blocks.
YourClientConstructor() {
LogUtils.setLoggerClass(org.apache.cxf.common.logging.Log4jLogger.class);
URL wsdlURL = YOurURL;//
//create the service
YourService = new YourService(wsdlURL, SERVICE_NAME);
port = yourService.getServicePort();
Client client = ClientProxy.getClient(port);
client.getInInterceptors().add(new LoggingInInterceptor());
client.getOutInterceptors().add(new LoggingOutInterceptor());
}
Then the inbound and outbound messages will be printed to Log4j file instead of the console. Make sure your log4j is configured properly
Upvotes: 21
Reputation: 151
In your spring context configuring below would log the request and response soap messsage.
<bean id="loggingFeature" class="org.apache.cxf.feature.LoggingFeature">
<property name="prettyLogging" value="true" />
</bean>
<cxf:bus>
<cxf:features>
<ref bean="loggingFeature" />
</cxf:features>
</cxf:bus>
Upvotes: 6
Reputation: 550
When configuring log4j.properties
, putting org.apache.cxf
logging level to INFO
is enough to see the plain SOAP messages:
log4j.logger.org.apache.cxf=INFO
DEBUG is too verbose.
Upvotes: 1