Reputation: 145
I am currently logging CXF using log4j as mentioned in CXF user guide. But the log file is flooding and becoming unmanageable with all IN/OUT payload logs.
I need to log incoming SOAP payload only when some fault/exception is generated as output. I understand that it will require to write custom interceptor, but is this possible to achieve?
Can anybody provide me some link/hint or may be some example working piece of code?
Thanks in Advance Tirthankar
Upvotes: 3
Views: 7965
Reputation: 2297
You need a custom Feature
to only log SOAP fault/exception.
Following is the source code of LoggingFeature.initializeProvider()
method. As you can see, fault interceptors are being added inside this method.
@Override
protected void initializeProvider(InterceptorProvider provider, Bus bus) {
if (limit == DEFAULT_LIMIT && inLocation == null
&& outLocation == null && !prettyLogging) {
provider.getInInterceptors().add(IN);
>>> provider.getInFaultInterceptors().add(IN);
provider.getOutInterceptors().add(OUT);
>>> provider.getOutFaultInterceptors().add(OUT);
} else {
LoggingInInterceptor in = new LoggingInInterceptor(limit);
in.setOutputLocation(inLocation);
in.setPrettyLogging(prettyLogging);
in.setShowBinaryContent(showBinary);
LoggingOutInterceptor out = new LoggingOutInterceptor(limit);
out.setOutputLocation(outLocation);
out.setPrettyLogging(prettyLogging);
out.setShowBinaryContent(showBinary);
provider.getInInterceptors().add(in);
provider.getInFaultInterceptors().add(in);
provider.getOutInterceptors().add(out);
provider.getOutFaultInterceptors().add(out);
}
}
You can write your own LoggingFeature
and override initializeProvider
as follows:
public class CustomLoggingFeature extends LoggingFeature {
@Override
protected void initializeProvider(InterceptorProvider provider, Bus bus) {
provider.getInFaultInterceptors().add(new LoggingInInterceptor(getLimit()));
provider.getOutFaultInterceptors().add(new LoggingOutInterceptor(getLimit()));
}
}
Then you may activate CustomLoggingFeature
as follows:
@WebService
@Features(classes = {CustomLoggingFeature.class})
public interface AssetServices {
}
Upvotes: 0
Reputation: 41
This link may help : http://www.madbit.org/blog/programming/942/how-to-log-apache-cxf-soap-request-and-response-using-log4j/#sthash.SOlB7sx6.CaTMsv3I.dpbs
You can do it by writing a custom interceptor and add bean ref as follows in your cxf.xml file :
<bean id="customIncomingSoapFaultInterceptor" class="com.tirtha.CustomIncomingSoapFaultInterceptor" />
<cxf:bus>
<cxf:inFaultInterceptors>
<ref bean="customIncomingSoapFaultInterceptor" />
</cxf:inFaultInterceptors>
</cxf:bus>
Sample custom interceptor:
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.binding.soap.Soap12;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class CustomIncomingSoapFaultInterceptor extends AbstractSoapInterceptor {
private static Log s_logger = LogFactory.getLog(CustomIncomingSoapFaultInterceptor.class);
public CustomIncomingSoapFaultInterceptor(){
// set phase here
//super(Phase.PRE_PROTOCOL);
super(Phase.RECEIVE);
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
Fault fault = null;
String soapMessage = null;
StringBuilder strMessage = null;
HttpServletRequest httpRequest = (HttpServletRequest) message.get(AbstractHTTPDestination.HTTP_REQUEST);
if (httpRequest != null) {
InputStream ist = message.getContent(InputStream.class);
if (ist != null) {
CachedOutputStream bos = new CachedOutputStream();
try {
IOUtils.copy(ist, bos);
bos.flush();
ist.close();
message.setContent(InputStream.class, bos.getInputStream());
soapMessage = new String(bos.getBytes());//this soap message is what you want
bos.close();
s_logger.debug("Soap Message: ---------->" + soapMessage==null?"null":soapMessage);
s_logger.debug("String Request: ---------->" + soapMessage);
} catch (IOException e) {
throw new Fault(e);
}
}
}
}
Upvotes: 4