SOAPHandler怪异的行为

时间:2018-07-23 09:51:03

标签: java xml web-services soap jax-ws

我有以下SOAPHandler

package fi.***.ws;

import java.io.StringWriter;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Set;

import javax.ejb.EJB;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import ***

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class MyLoggingHandler implements SOAPHandler<SOAPMessageContext> {

    @EJB private AsetusDAO asetusDAO;
    @EJB private SanomalokiDAO sanomalokiDAO;

    public void tallennaLokirivi(Suunta suunta, String palvelu, String sanoma) {
        Sanomaloki loki = new Sanomaloki();
        loki.setSuunta(new BigDecimal(suunta.getValue()));
        loki.setPalvelu(palvelu);
        loki.setSanoma(sanoma);
        sanomalokiDAO.tallennaLokirivi(loki);
    }

    public String getPalvelu(SOAPMessageContext ctx) {
        SOAPEnvelope msg;
        SOAPBody body;
        String operationName;
        try {
            msg = ctx.getMessage().getSOAPPart().getEnvelope();
            body = msg.getBody();
            operationName = body.getChildNodes().item(1).getLocalName();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        return operationName;
    }

    public String getSanomaXML(SOAPMessageContext ctx) {
        SOAPMessage message;
        String sanomaXML;

        final StringWriter sw = new StringWriter();

        try {
            message = ctx.getMessage();
            TransformerFactory.newInstance().newTransformer().transform(
                new DOMSource(message.getSOAPPart()),
                new StreamResult(sw));
            sanomaXML = sw.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        return sanomaXML;
    }

    public boolean isSanomalokiPaalla() {
        Asetus lokitus = asetusDAO.haeAsetus(AsetusDAO.Avain.A1_SANOMALOKI_PAALLA);
        return DatabaseConstants.A1_SANOMALOKI_PAALLA_1_VALUE.equals(lokitus.getArvo());
    }

    @Override
    public boolean handleMessage(SOAPMessageContext context) {

        if (!isSanomalokiPaalla())
            return true;

        String palvelu = getPalvelu(context);
        String sanoma = getSanomaXML(context);

        boolean isRequest = !((Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue();

        if (isRequest) {
            // request
            System.out.println("--- Logging handler message request ---");
            tallennaLokirivi(Suunta.SISAAN, palvelu, sanoma);

        } else {
            // response
            System.out.println("--- Logging handler message response ---");
            tallennaLokirivi(Suunta.ULOS, palvelu, sanoma);
        }
        return true; // return false;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {

        if (!isSanomalokiPaalla())
            return true;

        System.out.println("--- Logging handler message fault ---");

        String palvelu = getPalvelu(context);
        String sanoma = getSanomaXML(context);

        tallennaLokirivi(Suunta.ULOS, palvelu, sanoma);

        return true; // return false;
    }

    @Override
    public void close(MessageContext context) {
        System.out.println("--- close ---");
    }

    @Override
    public Set<QName> getHeaders() {
        System.out.println("--- getHeaders---");
        return Collections.emptySet();
    }

}

调用Web服务会返回以下错误

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <ns0:Fault xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2003/05/soap-envelope">
         <faultcode>ns0:Server</faultcode>
         <faultstring>Exception Description: The object [?], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[x-->x/text()]] with descriptor [XMLDescriptor(fi.***.PisteTyyppi --> [])], could not be converted to [class java.lang.Integer].
Internal Exception: java.lang.NumberFormatException: For input string: "?"</faultstring>
      </ns0:Fault>
   </S:Body>
</S:Envelope>

是导致此错误的getPalvelugetSanomaXML方法。但是,由于某些原因 catch子句未捕获到异常handleMessage方法实际上是在没有调用handleFault方法的情况下完成的。另外,如果我从处理程序中删除这些方法,Web服务实现将友好地绑定参数,并且不会引发任何错误。

显然,Java SOAP API在内部捕获异常并设置故障。为什么我在处理程序上遇到此错误,并且有什么方法可以捕获异常?

1 个答案:

答案 0 :(得分:0)

根据jax-ws 2.2 specification的9.3.2.1节,当您抛出一个非ProtocolException(或其子类)时,这是预期的行为,因此,如果您想通过handleFault方法处理那些异常您必须重新抛出ProtocolException而不是RuntimeException。另外,该handleFault方法必须位于单独的SOAPHandler中,因为消息交换模式将跳过当前句柄的handleFault并将错误传递给前一个。

Here,您可以看到不同情况下消息流的一些不错的框图。