如何覆盖cxf MessageSenderEndingInterceptor并控制handleMessage方法

时间:2016-07-04 21:42:27

标签: java web-services cxf

我使用jaxws:client标签和spring来消费webservices。 在上面的过程中,我想在调用webservice之前和之后使用cxf拦截器。

我能够使用带有webservice的cxf拦截器返回正确的soap错误和成功响应,但是在没有调用inFaultInterceptor的情况下 Http状态代码:404 以及当服务停止时...连接异常..

分析错误后..我发现异常被抛出了 https://cxf.apache.org/javadoc/latest/org/apache/cxf/interceptor/MessageSenderInterceptor.MessageSenderEndingInterceptor.html

 /**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
  * regarding copyright ownership. The ASF licenses this file
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License. You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */

 package org.apache.cxf.interceptor;

 import java.io.IOException;
 import java.util.ResourceBundle;

 import org.apache.cxf.common.i18n.BundleUtils;
 import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.transport.Conduit;

 /**
  * Takes the Conduit from the exchange and sends the message through it.
  */
  public class MessageSenderInterceptor extends AbstractPhaseInterceptor<Message> {
  private static final ResourceBundle BUNDLE = BundleUtils.getBundle(MessageSenderInterceptor.class);
  private MessageSenderEndingInterceptor ending = new MessageSenderEndingInterceptor();


  public MessageSenderInterceptor() {
       super(Phase.PREPARE_SEND);
  }

  public void handleMessage(Message message) {
      try {
           getConduit(message).prepare(message);
      } catch (IOException ex) {
        throw new Fault(new org.apache.cxf.common.i18n.Message("COULD_NOT_SEND", BUNDLE), ex);
         }    

          // Add a final interceptor to close the conduit
          message.getInterceptorChain().add(ending);
   }

      public class MessageSenderEndingInterceptor extends AbstractPhaseInterceptor<Message> {
        public MessageSenderEndingInterceptor() {
              super(Phase.PREPARE_SEND_ENDING);
          }

    public void handleMessage(Message message) throws Fault {
            try {
                getConduit(message).close(message);
            } catch (IOException e) {
                throw new Fault(new org.apache.cxf.common.i18n.Message("COULD_NOT_SEND", BUNDLE), e);
                }
        }
        }

    private Conduit getConduit(Message message) {
        Exchange exchange = message.getExchange();
        Conduit conduit = exchange.getConduit(message);
        if (conduit == null
            && (exchange.getOutMessage() != null
                || exchange.getOutFaultMessage() != null)) {
            conduit = OutgoingChainInterceptor.getBackChannelConduit(message);
        }
        return conduit;
    }

 }

我的问题:如何在我们的项目中覆盖此类,以便可以自定义内部类的handleMessage? 我必须在cxf故障之前获得对故障拦截器的控制而无法发送消息...

1 个答案:

答案 0 :(得分:2)

您可以使用添加到CXF Bus的FaultListener。监听器还将捕获http异常(例如404),允许您在将代码引发到调用方法之前执行代码。

例如

public class CxfFaultListenerImpl implements FaultListener{
    public boolean faultOccurred(final Exception exception,final String description,final Message message) {

        //return false to avoid standard CXF logging of exception
        return false;
    }
}

Spring CXF配置

<cxf:bus>
 <cxf:properties>
    <entry key="org.apache.cxf.logging.FaultListener">
        <bean id="cxfFaultListener" class="CxfFaultListenerImpl" />
    </entry>
 </cxf:properties>
</cxf:bus>