删除JAX-WS消息中的XML声明 [英] Removing XML declaration in JAX-WS message

查看:53
本文介绍了删除JAX-WS消息中的XML声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Java代码调用Web服务. 因此,我使用JAX-WS和JAXB从wsdl文件生成对象.

I'm trying to invoke a webservice using Java code. So I used JAX-WS and JAXB to generate my object from wsdl file.

当我调用Web服务时,它会以以下错误响应:

When I invoke the webservice it respond with this error:

Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: The [javax.xml.transform.TransformerException] occurred during XSLT transformation:  javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: The XML declaration must end with "?>".

Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: The [javax.xml.transform.TransformerException] occurred during XSLT transformation:  javax.xml.transform.TransformerException: org.xml.sax.SAXParseException: The XML declaration must end with "?>".
at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:189)
at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:122)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)

因此,我用Wireshark分析了正在发送的xml消息.并尝试使用soapUI重新发送.

So with wireshark I analysed the xml message that is being sent. And tried to resend it with soapUI.

发现我的xml包含xml声明

And found out that my xml contains the xml declaration

<?xml version='1.0' encoding='UTF-8'?>

当我从SoapUI删除它并重新发送它时.消息正常.

When I remove it from SoapUI and resend it. The message goes ok.

我的Java代码如下:

My java code goes like this:

public static Data receiveSIBS(webserviceclient.Data input) {

    webserviceclient.Starter service = new webserviceclient.Starter();
    webserviceclient.PortType port = service.getSOAPEventSource();

    BindingProvider bp = (BindingProvider) port;
    bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);

    return port.receiveSIBS(input);
}

在没有此xml声明的情况下,如何用Java生成消息? 因为xml消息都是使用 JAX-WS JAXB 生成的.

How can I generate my message in Java without this xml declaration? because the xml message is all generated with JAX-WS and JAXB.

感谢进阶!

推荐答案

找到了自己的解决方案!

Found my own solution!

首先,如其他文章所述,我实现了一个SOAPHandler来编辑这两个属性:

First, as referred in other post, I implemented a SOAPHandler to edit this two properties:

soapMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-16");
soapMsg.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");

但是,尽管这两个属性更改了handleMessage()方法中的消息实例,但它不会像这样发送,并且会发送带有默认xml声明的消息.

But although this two properties change message instance inside handleMessage() method, it won't be sent like it, and message with default xml declaration is sent.

代替设置此属性,解决方案是设置这两个NamespaceDeclaration:

Instead of setting this properties the solution was to set this two NamespaceDeclaration:

SOAPEnvelope env = sp.getEnvelope();
env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
env.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");

我不明白为什么会收到"XML声明必须以?>"结尾的错误.因为我的解决方案没有删除xml声明.可能与xml结构有关(但是我没有足够的知识来确认它).

I don't understand why we get "The XML declaration must end with "?>"" error. Because my solution didn't removed xml declaration. Might be related to xml structure (but I don't have enough knowledge to confirm it).

我需要引用 http://blog.jdevelop.eu/?p=67让我介绍此解决方案的帖子,而一些调试代码则来自此帖子.

I need to refer http://blog.jdevelop.eu/?p=67 post that let me to this solution, and some debug code is from this post.

下面,我放置了完整的CustomHandler类,以便它可以容纳任何人.

Following I put my complete CustomHandler class so it can held anyone.

import java.io.ByteArrayOutputStream;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

/**
 *
 * @author Daniel Chang Yan
 */
public class CustomHandler implements SOAPHandler<SOAPMessageContext> {

public boolean handleMessage(SOAPMessageContext context) {
    Boolean isOutbound
            = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    if (isOutbound != null && isOutbound) {
        SOAPMessage soapMsg = context.getMessage();
        try {
            //Properties always rewritten by jaxws, no matter what is set here
            //soapMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-16");
            //soapMsg.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");

            // get SOAP-Part
            SOAPPart sp = soapMsg.getSOAPPart();

            //edit Envelope
            SOAPEnvelope env = sp.getEnvelope();
            env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
            env.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");

        } catch (SOAPException e) {
            throw new RuntimeException(e);
        }

        // print SOAP-Message
        System.out.println("Direction=outbound (handleMessage)...");
        dumpSOAPMessage(soapMsg);

    } else {
        // INBOUND
        System.out.println("Direction=inbound (handleMessage)...");
        SOAPMessage msg = ((SOAPMessageContext) context).getMessage();
        dumpSOAPMessage(msg);

    }

    return true;
}

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

public boolean handleFault(SOAPMessageContext context) {
    System.out.println("ServerSOAPHandler.handleFault");
    boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    if (outbound) {
        System.out.println("Direction=outbound (handleFault)...");
    } else {
        System.out.println("Direction=inbound (handleFault)...");
    }
    if (!outbound) {
        try {
            SOAPMessage msg = ((SOAPMessageContext) context).getMessage();
            dumpSOAPMessage(msg);
            if (context.getMessage().getSOAPBody().getFault() != null) {
                String detailName = null;
                try {
                    detailName = context.getMessage().getSOAPBody().getFault().getDetail().getFirstChild().getLocalName();
                    System.out.println("detailName=" + detailName);
                } catch (Exception e) {
                }
            }
        } catch (SOAPException e) {
            e.printStackTrace();
        }
    }
    return true;
}

public void close(MessageContext mc) {
}

/**
 * Dump SOAP Message to console
 *
 * @param msg
 */
private void dumpSOAPMessage(SOAPMessage msg) {
    if (msg == null) {
        System.out.println("SOAP Message is null");
        return;
    }
    //System.out.println("");
    System.out.println("--------------------");
    System.out.println("DUMP OF SOAP MESSAGE");
    System.out.println("--------------------");
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        msg.writeTo(baos);
        System.out.println(baos.toString(getMessageEncoding(msg)));

        // show included values
        String values = msg.getSOAPBody().getTextContent();
        System.out.println("Included values:" + values);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * Returns the message encoding (e.g. utf-8)
 *
 * @param msg
 * @return
 * @throws javax.xml.soap.SOAPException
 */
private String getMessageEncoding(SOAPMessage msg) throws SOAPException {
    String encoding = "utf-8";
    if (msg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING) != null) {
        encoding = msg.getProperty(SOAPMessage.CHARACTER_SET_ENCODING).toString();
    }
    return encoding;
}
}

这篇关于删除JAX-WS消息中的XML声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆