Reputation: 363
By invoking a JAX-WS Webservice's operation through a HTTP POST request, we typically get the response in the format as the example below:
<?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>
I want to remove and/or modify the version of the XML declaration of the SOAP message response on the server side, i.e., I want to remove/modify this part from the response of my WS:
<?xml version="1.0" encoding="UTF-8" ?>
I have tried to remove it by using a JAX-WS SOAPMessage handler (see code below) but it did not work.
@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;
}
What am I doing wrong? Is this even possible??? If it is, do you have any suggestion on how to remove the XML declaration or modify it's version (to XML 1.1), for example??
Much appreciated for any help!
Upvotes: 2
Views: 6418
Reputation: 3006
To remove the XML declaration in a response of a JAX-WS service (which should not be needed, but we all ran into that one integration party that swears it breaks their system, right?), it's hard to find a one-size-fits-all solution. In the implementations that I debugged, most assume that you want the declaration, and add it unconditionally.
The safest approach that I could come up with was taking this dilemma outside of the JAX-WS scope. Instead, a servlet filter can be employed to modify the servlet response that was generated by the JAX-WS implementation.
This code (Servlet 3.0 compatible) creates a simple filter that employs a ServletResponseWrapper to modify the response, just before it's sent back to the client. For good measure, it only operates on 'text/xml' content.
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()
{
}
}
Upvotes: 1
Reputation: 1141
Do you really need to remove xml declaration?
I have a situation that it works if I send a soap message without xml declaration. And if I send a soap message with xml declaration, this error will be returned:
org.xml.sax.SAXParseException: The XML declaration must end with "?>"
I also tried to set WRITE_XML_DECLARATION with no success.
My 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");
Refer to Removing XML declaration in JAX-WS message for complete solution description
Upvotes: 0