This commit is contained in:
Arjen Poutsma
2008-01-22 11:48:38 +00:00
parent c35389b564
commit 3f837abffb
2 changed files with 71 additions and 38 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.ws.soap.axiom;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
@@ -36,11 +37,17 @@ import org.apache.axiom.soap.impl.llom.soap11.SOAP11Factory;
import org.apache.axiom.soap.impl.llom.soap12.SOAP12Factory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor;
import org.springframework.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping;
import org.springframework.ws.transport.TransportConstants;
import org.springframework.ws.transport.TransportInputStream;
@@ -48,13 +55,18 @@ import org.springframework.ws.transport.TransportInputStream;
* Axiom-specific implementation of the {@link org.springframework.ws.WebServiceMessageFactory WebServiceMessageFactory}
* interface. Creates {@link org.springframework.ws.soap.axiom.AxiomSoapMessage AxiomSoapMessages}.
* <p/>
* To increase reading performance on the the SOAP request created by this message context factory, you can set the
* <code>payloadCaching</code> property to <code>false</code> (default is <code>true</code>). This this will read the
* contents of the body directly from the stream. However, <strong>when this setting is enabled, the payload can only be
* read once</strong>. This means that any endpoint mappings or interceptors which are based on the message payload
* (such as the <code>PayloadRootQNameEndpointMapping</code>, the <code>PayloadValidatingInterceptor</code>, or the
* <code>PayloadLoggingInterceptor</code>) cannot be used. Instead, use an endpoint mapping that does not consume the
* payload (i.e. the <code>SoapActionEndpointMapping</code>).
* To increase reading performance on the the SOAP request created by this message factory, you can set the {@link
* #setPayloadCaching(boolean) payloadCaching} property to <code>false</code> (default is <code>true</code>). This this
* will read the contents of the body directly from the stream. However, <strong>when this setting is enabled, the
* payload can only be read once</strong>. This means that any endpoint mappings or interceptors which are based on the
* message payload (such as the {@link PayloadRootQNameEndpointMapping}, the {@link PayloadValidatingInterceptor}, or
* the {@link PayloadLoggingInterceptor}) cannot be used. Instead, use an endpoint mapping that does not consume the
* payload (i.e. the {@link SoapActionEndpointMapping}).
* <p/>
* Additionally, this message factory can cache large attachments to disk by setting the {@link
* #setAttachmentCaching(boolean) attachmentCaching} property to <code>true</code> (default is <code>false</code>).
* Optionally, the location where attachments are stored can be defined via the {@link #setAttachmentCacheDir(File)
* attachmentCacheDir} property (defaults to the system temp file path).
* <p/>
* Mostly derived from <code>org.apache.axis2.transport.http.HTTPTransportUtils</code> and
* <code>org.apache.axis2.transport.TransportUtils</code>, which we cannot use since they are not part of the Axiom
@@ -79,6 +91,12 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing
private boolean payloadCaching = true;
private boolean attachmentCaching = false;
private File attachmentCacheDir;
private int attachmentCacheThreshold = 4096;
// use SOAP 1.1 by default
private SOAPFactory soapFactory = new SOAP11Factory();
@@ -88,14 +106,51 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing
}
/**
* Indicates whether the SOAP Body payload should be cached or not. Default is <code>true</code>. Setting this to
* <code>false</code> will increase performance, but also result in the fact that the message payload can only be
* read once.
* Indicates whether the SOAP Body payload should be cached or not. Default is <code>true</code>.
* <p/>
* Setting this to <code>false</code> will increase performance, but also result in the fact that the message
* payload can only be read once.
*/
public void setPayloadCaching(boolean payloadCaching) {
this.payloadCaching = payloadCaching;
}
/**
* Indicates whether SOAP attachments should be cached or not. Default is <code>false</code>.
* <p/>
* Setting this to <code>true</code> will cause Axiom to store larger attachments on disk, rather than in memory.
* This decreases memory consumption, but decreases performance.
*/
public void setAttachmentCaching(boolean attachmentCaching) {
this.attachmentCaching = attachmentCaching;
}
/**
* Sets the directory where SOAP attachments will be stored. Only used when {@link #setAttachmentCaching(boolean)
* attachmentCaching} is set to <code>true</code>.
* <p/>
* The parameter should be an existing, writable directory. This property defaults to the temporary directory of the
* operating system (i.e. the value of the <code>java.io.tmpdir</code> system property).
*/
public void setAttachmentCacheDir(File attachmentCacheDir) {
Assert.notNull(attachmentCacheDir, "'attachmentCacheDir' must not be null");
Assert.isTrue(attachmentCacheDir.isDirectory(), "'attachmentCacheDir' must be a directory");
Assert.isTrue(attachmentCacheDir.canWrite(), "'attachmentCacheDir' must be writable");
this.attachmentCacheDir = attachmentCacheDir;
}
/**
* Sets the threshold for attachments caching, in bytes. Attachments larger than this threshold will be cached in
* the {@link #setAttachmentCacheDir(File) attachment cache directory}. Only used when {@link
* #setAttachmentCaching(boolean) attachmentCaching} is set to <code>true</code>.
* <p/>
* Defaults to 4096 bytes (i.e. 4 kilobytes).
*/
public void setAttachmentCacheThreshold(int attachmentCacheThreshold) {
Assert.isTrue(attachmentCacheThreshold > 0, "'attachmentCacheThreshold' must be larger than 0");
this.attachmentCacheThreshold = attachmentCacheThreshold;
}
public void setSoapVersion(SoapVersion version) {
if (SoapVersion.SOAP_11 == version) {
soapFactory = new SOAP11Factory();
@@ -113,6 +168,10 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing
if (logger.isInfoEnabled()) {
logger.info(payloadCaching ? "Enabled payload caching" : "Disabled payload caching");
}
if (attachmentCacheDir == null) {
String tempDir = System.getProperty("java.io.tmpdir");
setAttachmentCacheDir(new File(tempDir));
}
}
public WebServiceMessage createWebServiceMessage() {
@@ -172,7 +231,8 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing
private AxiomSoapMessage createMultiPartAxiomSoapMessage(InputStream inputStream,
String contentType,
String soapAction) throws XMLStreamException {
Attachments attachments = new Attachments(inputStream, contentType);
Attachments attachments = new Attachments(inputStream, contentType, attachmentCaching,
attachmentCacheDir.getAbsolutePath(), Integer.toString(attachmentCacheThreshold));
XMLStreamReader reader = inputFactory.createXMLStreamReader(attachments.getSOAPPartInputStream(),
getCharSetEncoding(attachments.getSOAPPartContentType()));
StAXSOAPModelBuilder builder;

View File

@@ -27,31 +27,4 @@ public class AxiomSoap11MessageFactoryTest extends AbstractSoap11MessageFactoryT
return factory;
}
/*
public void testCreateMtom() throws Exception {
SOAP11Factory factory = new SOAP11Factory();
SOAPEnvelope envelope = factory.getDefaultEnvelope();
OMNamespace namespace = factory.createOMNamespace("http://springframework.org/spring-ws/mtom", "sws");
OMElement element = factory.createOMElement("image", namespace);
envelope.getBody().addChild(element);
DataHandler dataHandler = new javax.activation.DataHandler(new FileDataSource("/Users/arjen/spring-ws/src/site/resources/images/spring-ws.png"));
//create an OMText node with the above DataHandler and set optimized to true
OMText textData = factory.createOMText(dataHandler, true);
element.addChild(textData);
OMOutputFormat format = new OMOutputFormat();
format.setDoOptimize(true);
format.setSOAP11(true);
format.setCharSetEncoding("UTF-8");
assertTrue(format.isOptimized());
OutputStream os = new BufferedOutputStream(new FileOutputStream(
"/Users/arjen/Projects/Spring/spring-ws/core/src/test/resources/org/springframework/ws/soap/soap11/soap11-mtom.bin"));
try {
envelope.serialize(os, format);
} finally {
os.close();
*/
}