删除/修改SOAP响应消息的XML声明

时间:2015-04-22 21:44:53

标签: java soap jax-ws

通过HTTP POST请求调用JAX-WS Webservice的操作,我们通常以下面的示例的格式获取响应:

<?xml version="1.0" encoding="UTF-8" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
 <S:Body>
    <ns2:helloResponse xmlns:ns2="http://test/">
       <return>Hello Foo!</return>
    </ns2:helloResponse>
 </S:Body>
</S:Envelope> 

我想删除和/或修改服务器端的SOAP消息响应的XML声明版本,即我想从我的WS的响应中删除/修改此部分:

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

我尝试使用JAX-WS SOAPMessage处理程序删除它(请参阅下面的代码),但它不起作用。

@Override
public boolean handleMessage(SOAPMessageContext context) {
    Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    if(isRequest) {
        try {
            final SOAPMessage message = context.getMessage();
            message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");
            message.saveChanges();
            context.setMessage(message);
        } catch (SOAPException e) {
            return false;
        }
    }
    return true;
}

我做错了什么?这甚至可能吗?如果是,您是否有任何关于如何删除XML声明或修改它的版本(到XML 1.1)的建议,例如??

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

要在JAX-WS服务的响应中删除XML声明(应该不需要,但我们都遇到了那个发誓它破坏了系统的集成方,对吗?) ,很难找到一个通用的解决方案。在我调试的实现中,大多数假设您想要声明,并无条件地添加它。

我能提出的最安全的方法是在JAX-WS范围之外采取这种困境。相反,可以使用servlet过滤器来修改由JAX-WS实现生成的servlet响应。

这段代码(与Servlet 3.0兼容)创建了一个简单的过滤器,它使用ServletResponseWrapper来修改响应,就在它被发送回客户端之前。为了更好地衡量,它只对“text / xml”内容进行操作。

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;

/**
 * A servlet filter that allows one to strip the XML declaration from xml-based
 * responses.
 *
 * @author Guus der Kinderen.
 */
@WebFilter( "/*" )
public class XmlDeclarationFilter implements Filter
{
    public void doFilter( ServletRequest request,
                          ServletResponse response,
                          FilterChain chain )
                          throws ServletException, IOException
    {
        try ( final Writer out = response.getWriter() )
        {
            // Will hold original response.
            final Wrapper wrapper = new Wrapper((HttpServletResponse) response );

            // Proceed with the request (will populate wrapper).
            chain.doFilter( request, wrapper );

            // Process the populated wrapper.
            if ( wrapper.getContentType().contains( "text/xml" ) )
            {
                // Modify the original content (strip the XML declaration).
                final String regex = "(?s)^\\s*\\<\\?xml.*?>";
                final String original = wrapper.toString();
                final String modified = original.replaceFirst( regex, "" );

                // Adjust the content length value to account for any changes.
                response.setContentLength( modified.length() );

                // Send out the modified content as a response.
                out.write( modified );
            }
            else
            {
                // Send out the original content, unmodified.
                out.write( wrapper.toString() );
            }
        }
    }

    /**
     * A response wrapper that buffers all output, and makes it available as 
     * a String.
     *
     * @author Guus der Kinderen.
     */
    public class Wrapper extends HttpServletResponseWrapper
    {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();

        public Wrapper( HttpServletResponse response )
        {
            super( response );
        }

        public String toString()
        {
            try
            {
                return baos.toString( "utf-8" );
            }
            catch ( UnsupportedEncodingException e )
            {
                return baos.toString();
            }
        }

        @Override
        public PrintWriter getWriter()
        {
            return new PrintWriter( baos );
        }

        @Override
        public ServletOutputStream getOutputStream() throws IOException
        {
            return new ServletOutputStream()
            {
                @Override
                public void write( int b ) throws IOException
                {
                    baos.write( b );
                }
            };
        }
    }

    public void init( FilterConfig config ) throws ServletException
    {
    }

    public void destroy()
    {
    }
}

答案 1 :(得分:0)

你真的需要删除xml声明吗?

如果我发送没有xml声明的soap消息,我有一种情况可行。 如果我发送带有xml声明的soap消息,则会返回此错误:

org.xml.sax.SAXParseException: The XML declaration must end with "?>"

我也尝试设置WRITE_XML_DECLARATION但没有成功。

我的解决方案是设置这两个NamespaceDeclaration:

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

有关完整的解决方案说明,请参阅Removing XML declaration in JAX-WS message