SWS-540 - Adding XML declaration to a response

Covariant return types for SoapMessageFactory
This commit is contained in:
Arjen Poutsma
2010-04-08 11:40:43 +00:00
parent 6c8ac54bb8
commit 9ada654f52
5 changed files with 92 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2007 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ public interface WebServiceMessageFactory {
* If the given stream is an instance of {@link org.springframework.ws.transport.TransportInputStream
* TransportInputStream}, the headers will be read from the request.
*
* @param inputStream the inputstream to read the message from
* @param inputStream the input stream to read the message from
* @return the created message
* @throws java.io.IOException if an I/O exception occurs
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2007 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,9 @@
package org.springframework.ws.soap;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.ws.WebServiceMessageFactory;
/**
@@ -38,4 +41,24 @@ public interface SoapMessageFactory extends WebServiceMessageFactory {
*/
void setSoapVersion(SoapVersion version);
/**
* Creates a new, empty <code>SoapMessage</code>.
*
* @return the empty message
*/
SoapMessage createWebServiceMessage();
/**
* Reads a {@link SoapMessage} from the given input stream.
* <p/>
* If the given stream is an instance of {@link org.springframework.ws.transport.TransportInputStream
* TransportInputStream}, the headers will be read from the request.
*
* @param inputStream the input stream to read the message from
* @return the created message
* @throws java.io.IOException if an I/O exception occurs
*/
SoapMessage createWebServiceMessage(InputStream inputStream) throws IOException;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ import javax.xml.stream.XMLStreamReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor;
import org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping;
import org.springframework.ws.soap.SoapMessageFactory;
@@ -191,11 +190,11 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing
}
}
public WebServiceMessage createWebServiceMessage() {
public AxiomSoapMessage createWebServiceMessage() {
return new AxiomSoapMessage(soapFactory, payloadCaching, langAttributeOnSoap11FaultString);
}
public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException {
public AxiomSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
Assert.isInstanceOf(TransportInputStream.class, inputStream,
"AxiomSoapMessageFactory requires a TransportInputStream");
TransportInputStream transportInputStream = (TransportInputStream) inputStream;
@@ -242,7 +241,7 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing
}
/** Creates an AxiomSoapMessage without attachments. */
private WebServiceMessage createAxiomSoapMessage(InputStream inputStream, String contentType, String soapAction)
private AxiomSoapMessage createAxiomSoapMessage(InputStream inputStream, String contentType, String soapAction)
throws XMLStreamException {
XMLStreamReader reader = inputFactory.createXMLStreamReader(inputStream, getCharSetEncoding(contentType));
String envelopeNamespace = getSoapEnvelopeNamespace(contentType);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,15 +21,17 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.soap.SoapMessageCreationException;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.SoapVersion;
@@ -63,6 +65,8 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB
private boolean langAttributeOnSoap11FaultString = true;
private Map<String, ?> messageProperties;
/** Default, empty constructor. */
public SaajSoapMessageFactory() {
}
@@ -82,6 +86,14 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB
this.messageFactory = messageFactory;
}
/**
* Sets the SAAJ message properties. These properties will be set on created messages.
* @see javax.xml.soap.SOAPMessage#setProperty(String, Object)
*/
public void setMessageProperties(Map<String, ?> messageProperties) {
this.messageProperties = messageProperties;
}
/**
* Defines whether a {@code xml:lang} attribute should be set on SOAP 1.1 {@code <faultstring>} elements.
* <p/>
@@ -90,7 +102,7 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB
*
* @see <a href="http://www.ws-i.org/Profiles/BasicProfile-1.1.html#SOAP_Fault_Language">WS-I Basic Profile 1.1</a>
*/
public void setlangAttributeOnSoap11FaultString(boolean langAttributeOnSoap11FaultString) {
public void setLangAttributeOnSoap11FaultString(boolean langAttributeOnSoap11FaultString) {
this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
}
@@ -152,20 +164,24 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB
}
}
public WebServiceMessage createWebServiceMessage() {
public SaajSoapMessage createWebServiceMessage() {
try {
return new SaajSoapMessage(messageFactory.createMessage(), langAttributeOnSoap11FaultString);
SOAPMessage saajMessage = messageFactory.createMessage();
postProcess(saajMessage);
return new SaajSoapMessage(saajMessage, langAttributeOnSoap11FaultString);
}
catch (SOAPException ex) {
throw new SoapMessageCreationException("Could not create empty message: " + ex.getMessage(), ex);
}
}
public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException {
public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
MimeHeaders mimeHeaders = parseMimeHeaders(inputStream);
try {
inputStream = checkForUtf8ByteOrderMark(inputStream);
return new SaajSoapMessage(messageFactory.createMessage(mimeHeaders, inputStream));
SOAPMessage saajMessage = messageFactory.createMessage(mimeHeaders, inputStream);
postProcess(saajMessage);
return new SaajSoapMessage(saajMessage);
}
catch (SOAPException ex) {
// SAAJ 1.3 RI has a issue with handling multipart XOP content types which contain "startinfo" rather than
@@ -176,7 +192,9 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB
contentType = contentType.replace("startinfo", "start-info");
mimeHeaders.setHeader(TransportConstants.HEADER_CONTENT_TYPE, contentType);
try {
return new SaajSoapMessage(messageFactory.createMessage(mimeHeaders, inputStream),
SOAPMessage saajMessage = messageFactory.createMessage(mimeHeaders, inputStream);
postProcess(saajMessage);
return new SaajSoapMessage(saajMessage,
langAttributeOnSoap11FaultString);
}
catch (SOAPException e) {
@@ -223,6 +241,20 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB
return pushbackInputStream;
}
/**
* Template method that allows for post-processing of the given {@link SOAPMessage}.
* <p>Default implementation sets {@linkplain SOAPMessage#setProperty(String, Object) message properties}, if any.
* @param soapMessage the message to post process
* @see #setMessageProperties(java.util.Map)
*/
protected void postProcess(SOAPMessage soapMessage) throws SOAPException {
if (!CollectionUtils.isEmpty(messageProperties)) {
for (Map.Entry<String, ?> entry : messageProperties.entrySet()) {
soapMessage.setProperty(entry.getKey(), entry.getValue());
}
}
}
public String toString() {
StringBuilder builder = new StringBuilder("SaajSoapMessageFactory[");
builder.append(SaajUtils.getSaajVersionString());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,12 +16,22 @@
package org.springframework.ws.soap.saaj;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.soap11.AbstractSoap11MessageFactoryTestCase;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class SaajSoap11MessageFactoryTest extends AbstractSoap11MessageFactoryTestCase {
@Override
@@ -30,5 +40,16 @@ public class SaajSoap11MessageFactoryTest extends AbstractSoap11MessageFactoryTe
return new SaajSoapMessageFactory(messageFactory);
}
@Test
public void properties() throws IOException {
Map<String, ?> properties = Collections.singletonMap(SOAPMessage.WRITE_XML_DECLARATION, "true");
((SaajSoapMessageFactory)messageFactory).setMessageProperties(properties);
SoapMessage soapMessage = (SoapMessage) messageFactory.createWebServiceMessage();
ByteArrayOutputStream os = new ByteArrayOutputStream();
soapMessage.writeTo(os);
String result = os.toString("UTF-8");
assertTrue("XML declaration not written", result.startsWith("<?xml version=\"1.0\""));
}
}