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?
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);
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>
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
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
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.
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.*
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);
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>
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 ;)
Source: Stackoverflow.com