How can I log with Log4J SOAP request and response

2019-01-22 14:06发布

问题:

I am having the next problem:

I want to log the SOAP requests/responses that land on my web service (server side). Trying to configure my web service in the wsdd file. I am always landing on pages like the next one:

How to use the org.apache.axis.handlers.LogHandler

Which recommends to configure the Apeche Axis LogHandler to log the request/response. That is not valid for me, since a)there is no way to link the log4j there, and b)I just am not able to make it work.

Does anyone know a way to make my log4j to log the request/responses?

回答1:

So after hours or Googling out there in the web, I decided to get adventurous and program my own handler. Is much easier than expected.

I made a class that extends the abstract class BasicHandler (org.apache.axis.handlers.BasicHandler), and implements the invoke method loging the request or the response. Here is my class, which I have baptized as SOAPLogHandler :

package com.mypackage.axishandlers;

import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
import org.apache.log4j.Logger;

public class SOAPLogHandler extends BasicHandler {

private static Logger LOG= Logger.getLogger(SOAPLogHandler.class);
private static final long serialVersionUID = 1L;

@Override
public void invoke(MessageContext msgContext) throws AxisFault {
    if(msgContext.getResponseMessage() != null && msgContext.getResponseMessage().getSOAPPart() != null) {
        LOG.info(" Response = " + msgContext.getResponseMessage().getSOAPPartAsString());
    } else {
        if(msgContext.getRequestMessage() != null && msgContext.getRequestMessage().getSOAPPartAsString() != null) {
            LOG.info(" Request = " + msgContext.getRequestMessage().getSOAPPartAsString());
        }    
    }
}  }

The idea is, to log first the request, and when processed, log the response. So, in the server-config.wsdd (or the wsdd file from your client if you are in the client side), we have to add a handler pointing to that class, and configure it to uses in the request/response chain:

1st add the handler

 <handler name="log" type="java:com.mypackage.axishandlers.SOAPLogHandler"/>

2nd add the use of that handler to the request/response from the http transport (focus on the log handler)

 <transport name="http">
  <requestFlow>
   <handler type="log"/>
   <handler type="URLMapper"/>
   <handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
  </requestFlow>
  <responseFlow>
   <handler type="log"/>
  </responseFlow>
...
 </transport>

With that, the magic should be done, and you should receive a pretty log from the request/responses!

Disclaimer: I am not really sure from what will happend if you use some kind of SOAP multipart thing.



回答2:

Save this file as "client-config.wsdd" in the working directory as you do for log4j.properties .

If you don't want to alter any code and debug your axis web service client, you can follow this method to log all incoming and outgoing soap messages.

<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

<handler name="log" type="java:org.apache.axis.handlers.LogHandler" >
    <parameter name="LogHandler.fileName" value="c:/logs/axis.log"/>
</handler>

<globalConfiguration>
    <requestFlow>
        <handler type="log" />
    </requestFlow>
    <responseFlow>
        <handler type="log" />
    </responseFlow>
</globalConfiguration>

<transport name="http"
    pivot="java:org.apache.axis.transport.http.HTTPSender" />

</deployment>


回答3:

You need to add an Axis logger in your log4.xml configuration file, like below:

<logger name="org.apache.axis.transport.http.HTTPSender">
   <level value="DEBUG"/>
   <appender-ref ref="someLogAppender"/>
</logger>

someLogAppender may be an existing Log4J appender, or you may want to define a dedicated one, like below:

<appender name="someLogAppender" class="org.apache.log4j.FileAppender">
   <param name="File" value="/my/path/to/axis.log" />
   <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d %-5p [%c] %m%n" />
   </layout>
</appender>


回答4:

I know its a old thread, but may be useful for people looking for answers.

For AXIS-1 Server side logging, update your server-config.wsdd like below. server-config.wsdd is under WEB-INF folder of your war file.

A new handler for log. The file name along with path is configurable.

<handler name="log" type="java:org.apache.axis.handlers.LogHandler">
  <parameter name="LogHandler.fileName" value="/tmp/req-res-axis.log" />
</handler>

You can also use the LogHandler.writeToConsole parameter with the value as "true" to log in your console log.

Then update the <globalConfiguration> section to have

<requestFlow>
 <handler type="log"/>         
</requestFlow>
<responseFlow> 
 <handler type="log"/>
</responseFlow>

If the requestFlow and responseFlow contains other handlers ,put the log as the first handler.

This should be only used for debugging purpose not for production. Since the logging is naive and do the normal write operation on the file without any buffer. Secondly, the log file will grow to GB's since there is no rollover mechanism.

For AXIS-1 Client Side logging, update your client-config.wsdd like below. The client-config.wsdd should go into your classpath directly under a root folder configured in the classpath not in any sub-folders. The best location is the same directory where your log4j.xml or log4j.properties file is present(Thanks to #MukeshKoshyM post above).

    <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

    <handler name="log" type="java:org.apache.axis.handlers.LogHandler" >
     <parameter name="LogHandler.fileName" value="/tmp/axis_req_res.log"/>
    </handler>

    <globalConfiguration>
      <requestFlow>
        <handler type="log" />
     </requestFlow>
     <responseFlow>
        <handler type="log" />
     </responseFlow>
    </globalConfiguration>

<transport name="http"
    pivot="java:org.apache.axis.transport.http.HTTPSender" />
</deployment>

The same issue mentioned for server side logging is applicable for client side as well.

For production, write your own log handler by extending org.apache.axis.handlers.BasicHandler and configure the class file in the handler. Please look the above answer from #raspayu to configure your own. To log the faults override the public void onFault(MessageContext msgContext) method in your Handler.



回答5:

A solution to log the Axis Faults is extend the OnFault method :

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;

public class SOAPLogHandler extends BasicHandler {

  private static final String AXIS = "AXIS";
  private static final String AXIS_FAULT = "AXIS FAULT";
  private static Logger LOG = LoggerFactory.getLogger(SOAPLogHandler.class);
  private static final long serialVersionUID = 1;

  @Override
  public void invoke(MessageContext msgContext) throws AxisFault {
    logMessage(AXIS, msgContext);
  }

  @Override
  public void onFault(MessageContext msgContext) {
    try {            
        logMessage(AXIS_FAULT,msgContext);
    } catch (AxisFault axisFault) {
        LOG.error("Error on logging messages ",axisFault);
    }
  }

  private void logMessage(String preamble, MessageContext msgContext) throws AxisFault {
    if (msgContext.getResponseMessage() != null && msgContext.getResponseMessage().getSOAPPart() != null) {
        LOG.info("{} Response ={}",preamble ,msgContext.getResponseMessage().getSOAPPartAsString());
        return;
    }

    if (msgContext.getRequestMessage() != null && msgContext.getRequestMessage().getSOAPPartAsString() != null) {
        LOG.info("{} Request={}",preamble,msgContext.getRequestMessage().getSOAPPartAsString());
    }
  }
}

It is also mandatory to set the handler in the global configuration request flow, in the wsdd file will be something like this :

<globalConfiguration>     
  <requestFlow>
    <handler type="log" />
  </requestFlow>
  <responseFlow>
    <handler type="log" />
  </responseFlow>
</globalConfiguration>

<handler name="log" type="java:your.package.SOAPLogHandler"/>


回答6:

Axis by default is checking for file client-config.wsdd. We need to keep this file in the location same as log4j.xml or log4j.properties. Log file will be generated at the location specified on log handeller. Ensure the folder structure exists.

mukesh



标签: soap log4j axis