Skip to content

Commit 3f837ab

Browse files
committed
SWS-246
1 parent c35389b commit 3f837ab

File tree

2 files changed

+71
-38
lines changed

2 files changed

+71
-38
lines changed

core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessageFactory.java

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.ws.soap.axiom;
1818

19+
import java.io.File;
1920
import java.io.IOException;
2021
import java.io.InputStream;
2122
import java.util.Iterator;
@@ -36,25 +37,36 @@
3637
import org.apache.axiom.soap.impl.llom.soap12.SOAP12Factory;
3738
import org.apache.commons.logging.Log;
3839
import org.apache.commons.logging.LogFactory;
40+
3941
import org.springframework.beans.factory.InitializingBean;
42+
import org.springframework.util.Assert;
4043
import org.springframework.util.StringUtils;
4144
import org.springframework.ws.WebServiceMessage;
45+
import org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor;
46+
import org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping;
4247
import org.springframework.ws.soap.SoapMessageFactory;
4348
import org.springframework.ws.soap.SoapVersion;
49+
import org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor;
50+
import org.springframework.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping;
4451
import org.springframework.ws.transport.TransportConstants;
4552
import org.springframework.ws.transport.TransportInputStream;
4653

4754
/**
4855
* Axiom-specific implementation of the {@link org.springframework.ws.WebServiceMessageFactory WebServiceMessageFactory}
4956
* interface. Creates {@link org.springframework.ws.soap.axiom.AxiomSoapMessage AxiomSoapMessages}.
5057
* <p/>
51-
* To increase reading performance on the the SOAP request created by this message context factory, you can set the
52-
* <code>payloadCaching</code> property to <code>false</code> (default is <code>true</code>). This this will read the
53-
* contents of the body directly from the stream. However, <strong>when this setting is enabled, the payload can only be
54-
* read once</strong>. This means that any endpoint mappings or interceptors which are based on the message payload
55-
* (such as the <code>PayloadRootQNameEndpointMapping</code>, the <code>PayloadValidatingInterceptor</code>, or the
56-
* <code>PayloadLoggingInterceptor</code>) cannot be used. Instead, use an endpoint mapping that does not consume the
57-
* payload (i.e. the <code>SoapActionEndpointMapping</code>).
58+
* To increase reading performance on the the SOAP request created by this message factory, you can set the {@link
59+
* #setPayloadCaching(boolean) payloadCaching} property to <code>false</code> (default is <code>true</code>). This this
60+
* will read the contents of the body directly from the stream. However, <strong>when this setting is enabled, the
61+
* payload can only be read once</strong>. This means that any endpoint mappings or interceptors which are based on the
62+
* message payload (such as the {@link PayloadRootQNameEndpointMapping}, the {@link PayloadValidatingInterceptor}, or
63+
* the {@link PayloadLoggingInterceptor}) cannot be used. Instead, use an endpoint mapping that does not consume the
64+
* payload (i.e. the {@link SoapActionEndpointMapping}).
65+
* <p/>
66+
* Additionally, this message factory can cache large attachments to disk by setting the {@link
67+
* #setAttachmentCaching(boolean) attachmentCaching} property to <code>true</code> (default is <code>false</code>).
68+
* Optionally, the location where attachments are stored can be defined via the {@link #setAttachmentCacheDir(File)
69+
* attachmentCacheDir} property (defaults to the system temp file path).
5870
* <p/>
5971
* Mostly derived from <code>org.apache.axis2.transport.http.HTTPTransportUtils</code> and
6072
* <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
7991

8092
private boolean payloadCaching = true;
8193

94+
private boolean attachmentCaching = false;
95+
96+
private File attachmentCacheDir;
97+
98+
private int attachmentCacheThreshold = 4096;
99+
82100
// use SOAP 1.1 by default
83101
private SOAPFactory soapFactory = new SOAP11Factory();
84102

@@ -88,14 +106,51 @@ public AxiomSoapMessageFactory() {
88106
}
89107

90108
/**
91-
* Indicates whether the SOAP Body payload should be cached or not. Default is <code>true</code>. Setting this to
92-
* <code>false</code> will increase performance, but also result in the fact that the message payload can only be
93-
* read once.
109+
* Indicates whether the SOAP Body payload should be cached or not. Default is <code>true</code>.
110+
* <p/>
111+
* Setting this to <code>false</code> will increase performance, but also result in the fact that the message
112+
* payload can only be read once.
94113
*/
95114
public void setPayloadCaching(boolean payloadCaching) {
96115
this.payloadCaching = payloadCaching;
97116
}
98117

118+
/**
119+
* Indicates whether SOAP attachments should be cached or not. Default is <code>false</code>.
120+
* <p/>
121+
* Setting this to <code>true</code> will cause Axiom to store larger attachments on disk, rather than in memory.
122+
* This decreases memory consumption, but decreases performance.
123+
*/
124+
public void setAttachmentCaching(boolean attachmentCaching) {
125+
this.attachmentCaching = attachmentCaching;
126+
}
127+
128+
/**
129+
* Sets the directory where SOAP attachments will be stored. Only used when {@link #setAttachmentCaching(boolean)
130+
* attachmentCaching} is set to <code>true</code>.
131+
* <p/>
132+
* The parameter should be an existing, writable directory. This property defaults to the temporary directory of the
133+
* operating system (i.e. the value of the <code>java.io.tmpdir</code> system property).
134+
*/
135+
public void setAttachmentCacheDir(File attachmentCacheDir) {
136+
Assert.notNull(attachmentCacheDir, "'attachmentCacheDir' must not be null");
137+
Assert.isTrue(attachmentCacheDir.isDirectory(), "'attachmentCacheDir' must be a directory");
138+
Assert.isTrue(attachmentCacheDir.canWrite(), "'attachmentCacheDir' must be writable");
139+
this.attachmentCacheDir = attachmentCacheDir;
140+
}
141+
142+
/**
143+
* Sets the threshold for attachments caching, in bytes. Attachments larger than this threshold will be cached in
144+
* the {@link #setAttachmentCacheDir(File) attachment cache directory}. Only used when {@link
145+
* #setAttachmentCaching(boolean) attachmentCaching} is set to <code>true</code>.
146+
* <p/>
147+
* Defaults to 4096 bytes (i.e. 4 kilobytes).
148+
*/
149+
public void setAttachmentCacheThreshold(int attachmentCacheThreshold) {
150+
Assert.isTrue(attachmentCacheThreshold > 0, "'attachmentCacheThreshold' must be larger than 0");
151+
this.attachmentCacheThreshold = attachmentCacheThreshold;
152+
}
153+
99154
public void setSoapVersion(SoapVersion version) {
100155
if (SoapVersion.SOAP_11 == version) {
101156
soapFactory = new SOAP11Factory();
@@ -113,6 +168,10 @@ public void afterPropertiesSet() throws Exception {
113168
if (logger.isInfoEnabled()) {
114169
logger.info(payloadCaching ? "Enabled payload caching" : "Disabled payload caching");
115170
}
171+
if (attachmentCacheDir == null) {
172+
String tempDir = System.getProperty("java.io.tmpdir");
173+
setAttachmentCacheDir(new File(tempDir));
174+
}
116175
}
117176

118177
public WebServiceMessage createWebServiceMessage() {
@@ -172,7 +231,8 @@ private WebServiceMessage createAxiomSoapMessage(InputStream inputStream, String
172231
private AxiomSoapMessage createMultiPartAxiomSoapMessage(InputStream inputStream,
173232
String contentType,
174233
String soapAction) throws XMLStreamException {
175-
Attachments attachments = new Attachments(inputStream, contentType);
234+
Attachments attachments = new Attachments(inputStream, contentType, attachmentCaching,
235+
attachmentCacheDir.getAbsolutePath(), Integer.toString(attachmentCacheThreshold));
176236
XMLStreamReader reader = inputFactory.createXMLStreamReader(attachments.getSOAPPartInputStream(),
177237
getCharSetEncoding(attachments.getSOAPPartContentType()));
178238
StAXSOAPModelBuilder builder;

core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap11MessageFactoryTest.java

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,4 @@ protected WebServiceMessageFactory createMessageFactory() throws Exception {
2727
return factory;
2828
}
2929

30-
/*
31-
public void testCreateMtom() throws Exception {
32-
SOAP11Factory factory = new SOAP11Factory();
33-
SOAPEnvelope envelope = factory.getDefaultEnvelope();
34-
35-
OMNamespace namespace = factory.createOMNamespace("http://springframework.org/spring-ws/mtom", "sws");
36-
OMElement element = factory.createOMElement("image", namespace);
37-
envelope.getBody().addChild(element);
38-
DataHandler dataHandler = new javax.activation.DataHandler(new FileDataSource("/Users/arjen/spring-ws/src/site/resources/images/spring-ws.png"));
39-
40-
//create an OMText node with the above DataHandler and set optimized to true
41-
OMText textData = factory.createOMText(dataHandler, true);
42-
43-
element.addChild(textData);
44-
45-
OMOutputFormat format = new OMOutputFormat();
46-
format.setDoOptimize(true);
47-
format.setSOAP11(true);
48-
format.setCharSetEncoding("UTF-8");
49-
assertTrue(format.isOptimized());
50-
OutputStream os = new BufferedOutputStream(new FileOutputStream(
51-
"/Users/arjen/Projects/Spring/spring-ws/core/src/test/resources/org/springframework/ws/soap/soap11/soap11-mtom.bin"));
52-
try {
53-
envelope.serialize(os, format);
54-
} finally {
55-
os.close();
56-
*/
5730
}

0 commit comments

Comments
 (0)