【问题标题】:CXF 3.1 wsdl2java logging with Log4j2CXF 3.1 wsdl2java 使用 Log4j2 进行日志记录
【发布时间】:2016-05-19 15:39:59
【问题描述】:

我使用 CXF 3.1 wsdl2java 生成了我的服务,所以没有 cxf.xml。

我正在尝试将服务的请求和响应 XML 添加到我的 log4j2 设置中。由于版本更改等原因存在大量冲突信息。我的请求/响应 xml CXF 日志记录文件始终为空。

这是最接近我的设置:How to log CXF webservice requests with log4j2?

所以我的 log4j2.xml 中有以下内容

    <logger name="org.apache.cxf" additivity="false" level="info">
            <AppenderRef ref="APP_LOG_FILE"/>
    </logger>
    <logger name="org.apache.cxf.interceptor.LoggingInInterceptor" additivity="false" level="info">
        <AppenderRef ref="WS_LOG_FILE" />
    </logger>
    <logger name="org.apache.cxf.interceptor.LoggingOutInterceptor" additivity="false" level="info">
        <AppenderRef ref="WS_LOG_FILE" />
    </logger>

没有显示附加程序,但它们在那里,填充了 APP_LOG_FILE 但 WS_LOG_FILE 附加程序文件始终为空,同时交换消息。

我添加了一个包含此内容的 META-INF/cxf/org.apache.cxf.Logger 文件

org.apache.cxf.common.logging.Slf4jLogger

在运行我的 jar 时,我还尝试使用附加的命令行参数来替代 cxf.Logger 文件:

-Dorg.apache.cxf.Logger=org.apache.cxf.common.logging.Slf4jLogger

我添加了额外的依赖:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.0</version>
</dependency>

我在日志拦截器(它们是必需的还是 log4j2.xml 中配置的替代品?)和没有它们的情况下都尝试了以下操作,如当前注释掉的那样。

    GetComparisonDecisionService equinitiComparisonService = new GetComparisonDecisionService();
    GetComparisonDecisionInterface comparison = equinitiComparisonService.getGetComparisonDecision();
/*
    Client client = ClientProxy.getClient(equinitiComparisonService.getPort(GetComparisonDecisionInterface.class));
    client.getInInterceptors().add(new LoggingInInterceptor());
    client.getOutInterceptors().add(new LoggingOutInterceptor());
*/
    GetComparisonDecisionCallParameter comparisonDecisionCallParameter = new GetComparisonDecisionCallParameter();
    comparisonDecisionCallParameter.setSecurityToken(token);
    comparisonDecisionCallParameter.setComparisonApplication(equinitiApp);

    GetComparisonDecisionResponseParameter eqDescn = comparison.getComparisonDecision(comparisonDecisionCallParameter);

在这一点上我已经没有想法了。 cxf 文档非常简洁。

【问题讨论】:

  • 对于 CXF @Feature-Annotation:@Features(features = "org.apache.cxf.feature.LoggingFeature")
  • 那行得通。但有趣的是,使用 wdsl2java 您生成了一个类,然后需要手动编辑以添加记录所需的 @Features 注释。部分违背了生成 SOAP 客户端代码的目的。可惜我无法将评论标记为正确答案...

标签: java cxf log4j2


【解决方案1】:

根据要求作为答案:对于 CXF @Features(features = "org.apache.cxf.feature.LoggingFeature")。

【讨论】:

  • 我知道这有点老了,但我也处于同样的情况。我应该把这个注释放在哪里?查看问题中的代码,我看不到可以使用它的地方。我知道它应该在暴露 WebServicePort 的类上,但我无法触及该类(它是由 wsdl2java 从 WSDL 文件生成的)......我错过了什么?
【解决方案2】:

这是我想出的另一种解决方法,因为我无法使公认的解决方案发挥作用。这个想法是为您的服务定义一个处理程序,并将记录 SOAP 信封的责任委托给该处理程序。我们是在重新发明轮子,因为这个功能显然已经存在并且只需要激活,但如果你无法让它工作,你可能想试试这个。

定义一个实现 SOAPHandler 接口的自定义类

public class LoggingMessageHandler implements SOAPHandler<SOAPMessageContext> {

    // this is a  static instance of Logback's LoggerFactory.getLogger
    // exposed by the my.personal.package.logging.soap.SOAPMessageLogger class
    // all SOAP envelopes are logged by this logger
    private Logger logger = SOAPMessageLogger.getLogger();

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        final StringWriter sw = new StringWriter();
        try {
            TransformerFactory.newInstance().newTransformer().transform(
                    new DOMSource(context.getMessage().getSOAPPart()),
                    new StreamResult(sw));

            // I'm formatting the log output so that every request or response only takes a single row in the log file
            // this way the file is easier to go through, weighs less, and SOAP messages are easier to copy-paste
            String SOAPMessageString = sw.toString().replaceAll("[\\n\\t ]", "");
            if((Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {
                logger.info("{} REQUEST:\n{}", new Object[]{(context.get(MessageContext.WSDL_OPERATION)), SOAPMessageString});
            }
            else {
                logger.info("{} RESPONSE:\n{}", new Object[]{(context.get(MessageContext.WSDL_OPERATION)), SOAPMessageString});
            }
        } catch (Exception e) {
            logger.warn("Could not log SOAP envelope: "  + e.getMessage());
        }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        logger.warn("handleFault handler was fired, will attempt to retrieve and log message details...");
        final StringWriter sw = new StringWriter();
        try {
            TransformerFactory.newInstance().newTransformer().transform(
                    new DOMSource(context.getMessage().getSOAPPart()),
                    new StreamResult(sw));
            logger.warn(sw.toString());
        } catch (Exception e) {
            logger.warn("Could not log SOAP envelope: "  + e.getMessage());
        }
        return true;
    }

    @Override
    public void close(MessageContext context) {
        logger.trace("Closing!");
    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }
}

定义一个实现 HandlerResolver 接口的自定义类

public class LoggingMessageHandlerResolver implements HandlerResolver {
    @Override
    public List<Handler> getHandlerChain(PortInfo portInfo) {
        return Collections.singletonList(new LoggingMessageHandler());
    }
}

最后,当您将代理实例化为远程 SOAP Web 服务时,将您的自定义 LoggingHandlerResolver 设置为其解析器:

public MyRemoteServicePort getServicePort() {
    MyRemoteService myRemoteService = new MyRemoteService(new URL(webServicesBaseURL+myRemoteWsdlPath));
    myRemoteService.setHandlerResolver(new LoggingMessageHandlerResolver());
    return myRemoteService.getMyRemotePort();
}

这样,每次通过 MyRemoteServicePort 发送/接收消息时,它都会被 handleMessage 方法拦截,该方法将记录它。您当然可以配置 Logback(或您想使用的任何日志记录机制),以便根据自己的喜好自定义该日志输出。

【讨论】:

    【解决方案3】:

    查看 Frank 的评论,它解决了问题。

    我注意到在 CXF 网站上寻找登录信息的明显位置 - http://cxf.apache.org/docs/debugging-and-logging.html 没有提到这种方法!?

    【讨论】:

    • 如果弗兰克的回答解决了问题,我建议将其标记为答案(并可选择投票),以便他获得声誉积分。
    猜你喜欢
    • 2017-12-20
    • 2014-10-30
    • 2017-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多