SWS-496 - Added Axiom Spring-WS MTOM client

This commit is contained in:
Arjen Poutsma
2009-05-18 10:14:46 +00:00
parent fe63e18002
commit d2b9b02c3f
10 changed files with 336 additions and 94 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006 the original author or authors.
* Copyright 2002-2009 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.
@@ -73,6 +73,8 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
private final boolean langAttributeOnSoap11FaulString;
private OMOutputFormat outputFormat;
/**
* Create a new, empty <code>AxiomSoapMessage</code>.
*
@@ -154,6 +156,15 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
this.soapAction = EMPTY_SOAP_ACTION;
}
/**
* Sets the {@link OMOutputFormat} to be used when writing the message.
*
* @see #writeTo(java.io.OutputStream)
*/
public void setOutputFormat(OMOutputFormat outputFormat) {
this.outputFormat = outputFormat;
}
public SoapEnvelope getEnvelope() {
if (envelope == null) {
try {
@@ -212,24 +223,13 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
public void writeTo(OutputStream outputStream) throws IOException {
try {
String charsetEncoding = axiomMessage.getCharsetEncoding();
OMOutputFormat format = new OMOutputFormat();
format.setCharSetEncoding(charsetEncoding);
format.setSOAP11(getVersion() == SoapVersion.SOAP_11);
boolean hasAttachments = !attachments.getContentIDSet().isEmpty();
if (hasAttachments) {
if (isXopPackage()) {
format.setDoOptimize(true);
}
else {
format.setDoingSWA(true);
}
}
OMOutputFormat outputFormat = getOutputFormat();
if (outputStream instanceof TransportOutputStream) {
TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
String contentType = format.getContentType();
if (!hasAttachments) {
String contentType = outputFormat.getContentType();
if (!(outputFormat.isDoingSWA() || outputFormat.isOptimized())) {
String charsetEncoding = axiomMessage.getCharsetEncoding();
contentType += "; charset=" + charsetEncoding;
}
if (SoapVersion.SOAP_11 == getVersion()) {
@@ -240,15 +240,15 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
}
transportOutputStream.addHeader(TransportConstants.HEADER_CONTENT_TYPE, contentType);
}
if (!(format.isOptimized()) & format.isDoingSWA()) {
writeSwAMessage(outputStream, format);
if (!(outputFormat.isOptimized()) & outputFormat.isDoingSWA()) {
writeSwAMessage(outputStream, outputFormat);
}
else {
if (payloadCaching) {
axiomMessage.serialize(outputStream, format);
axiomMessage.serialize(outputStream, outputFormat);
}
else {
axiomMessage.serializeAndConsume(outputStream, format);
axiomMessage.serializeAndConsume(outputStream, outputFormat);
}
}
outputStream.flush();
@@ -261,6 +261,26 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
}
}
private OMOutputFormat getOutputFormat() {
if (outputFormat != null) {
return outputFormat;
}
else {
String charsetEncoding = axiomMessage.getCharsetEncoding();
OMOutputFormat outputFormat = new OMOutputFormat();
outputFormat.setCharSetEncoding(charsetEncoding);
outputFormat.setSOAP11(getVersion() == SoapVersion.SOAP_11);
if (isXopPackage()) {
outputFormat.setDoOptimize(true);
}
else if (!attachments.getContentIDSet().isEmpty()) {
outputFormat.setDoingSWA(true);
}
return outputFormat;
}
}
private void writeSwAMessage(OutputStream outputStream, OMOutputFormat format)
throws XMLStreamException, UnsupportedEncodingException {
StringWriter writer = new StringWriter();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006 the original author or authors.
* Copyright 2002-2009 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.
@@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Locale;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
@@ -235,6 +236,7 @@ public class AxiomSoapMessageFactory implements SoapMessageFactory, Initializing
}
private boolean isMultiPartRelated(String contentType) {
contentType = contentType.toLowerCase(Locale.ENGLISH);
return contentType.indexOf(MULTI_PART_RELATED_CONTENT_TYPE) != -1;
}

View File

@@ -30,6 +30,8 @@
<remoteRepository refid="java.net"/>
<dependency groupId="org.springframework" artifactId="spring-core" version="2.5.6"/>
<dependency groupId="org.springframework.ws" artifactId="spring-ws-core" version="1.5.6"/>
<dependency groupId="org.apache.ws.commons.axiom" artifactId="axiom-api" version="1.2.8"/>
<dependency groupId="org.apache.ws.commons.axiom" artifactId="axiom-impl" version="1.2.8"/>
</artifact:dependencies>
<artifact:dependencies pathId="runtime.classpath">
@@ -74,7 +76,7 @@
</target>
<target name="run" depends="build">
<java classname="org.springframework.ws.samples.mtom.client.sws.MtomClient" fork="true" failonerror="true">
<java classname="org.springframework.ws.samples.mtom.client.sws.Driver" fork="true" failonerror="true">
<jvmarg value="-Djava.awt.headless=true"/>
<arg path="../spring-ws-logo.png"/>
<classpath refid="compile.classpath"/>

View File

@@ -0,0 +1,150 @@
/*
* Copyright 2002-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.samples.mtom.client.sws;
import java.io.IOException;
import java.util.Iterator;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.imageio.ImageIO;
import javax.xml.transform.TransformerException;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.OMText;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPMessage;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceMessageExtractor;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.axiom.AxiomSoapMessage;
import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory;
import org.springframework.ws.soap.client.SoapFaultClientException;
/**
* Simple client that demonstartes MTOM by invoking <code>StoreImage</code> and <code>LoadImage</code> using a
* WebServiceTemplate and Axiom.
*
* @author Arjen Poutsma
*/
public class AxiomMtomClient extends WebServiceGatewaySupport {
private StopWatch stopWatch = new StopWatch(ClassUtils.getShortName(getClass()));
public AxiomMtomClient(AxiomSoapMessageFactory messageFactory) {
super(messageFactory);
}
public void doIt(String path) {
try {
store(path);
load(path);
System.out.println(stopWatch.prettyPrint());
}
catch (SoapFaultClientException ex) {
System.err.format("SOAP Fault Code %1s%n", ex.getFaultCode());
System.err.format("SOAP Fault String: %1s%n", ex.getFaultStringOrReason());
}
}
private void store(final String path) {
stopWatch.start("store");
getWebServiceTemplate().sendAndReceive(new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
AxiomSoapMessage soapMessage = (AxiomSoapMessage) message;
SOAPMessage axiomMessage = soapMessage.getAxiomMessage();
SOAPFactory factory = (SOAPFactory) axiomMessage.getOMFactory();
SOAPBody body = axiomMessage.getSOAPEnvelope().getBody();
OMNamespace ns =
factory.createOMNamespace("http://www.springframework.org/spring-ws/samples/mtom", "tns");
OMElement storeImageRequestElement = factory.createOMElement("StoreImageRequest", ns);
body.addChild(storeImageRequestElement);
OMElement nameElement = factory.createOMElement("name", ns);
storeImageRequestElement.addChild(nameElement);
nameElement.setText(StringUtils.getFilename(path));
OMElement imageElement = factory.createOMElement("image", ns);
storeImageRequestElement.addChild(imageElement);
DataSource dataSource = new FileDataSource(path);
DataHandler dataHandler = new DataHandler(dataSource);
OMText text = factory.createOMText(dataHandler, true);
imageElement.addChild(text);
OMOutputFormat outputFormat = new OMOutputFormat();
outputFormat.setSOAP11(true);
outputFormat.setDoOptimize(true);
soapMessage.setOutputFormat(outputFormat);
}
}, new WebServiceMessageExtractor() {
public Object extractData(WebServiceMessage message) throws IOException, TransformerException {
return null;
}
});
stopWatch.stop();
}
private void load(final String path) {
final StringBuilder name = new StringBuilder();
stopWatch.start("load");
java.awt.Image image = (java.awt.Image) getWebServiceTemplate().sendAndReceive(new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
SOAPMessage axiomMessage = ((AxiomSoapMessage) message).getAxiomMessage();
SOAPFactory factory = (SOAPFactory) axiomMessage.getOMFactory();
SOAPBody body = axiomMessage.getSOAPEnvelope().getBody();
OMNamespace ns =
factory.createOMNamespace("http://www.springframework.org/spring-ws/samples/mtom", "tns");
OMElement loadImageRequestElement = factory.createOMElement("LoadImageRequest", ns);
loadImageRequestElement.setText(StringUtils.getFilename(path));
body.addChild(loadImageRequestElement);
}
}, new WebServiceMessageExtractor() {
public Object extractData(WebServiceMessage message) throws IOException, TransformerException {
SOAPMessage axiomMessage = ((AxiomSoapMessage) message).getAxiomMessage();
SOAPBody body = axiomMessage.getSOAPEnvelope().getBody();
OMElement loadImageResponseElement = (OMElement) body.getChildElements().next();
Assert.isTrue("LoadImageResponse".equals(loadImageResponseElement.getLocalName()));
Iterator childElements = loadImageResponseElement.getChildElements();
OMElement nameElement = (OMElement) childElements.next();
Assert.isTrue("name".equals(nameElement.getLocalName()));
name.append(nameElement.getText());
OMElement imageElement = (OMElement) childElements.next();
Assert.isTrue("image".equals(imageElement.getLocalName()));
OMText text = (OMText) imageElement.getFirstOMChild();
DataHandler dataHandler = (DataHandler) text.getDataHandler();
return ImageIO.read(dataHandler.getInputStream());
}
});
stopWatch.stop();
logger.info("Received image " + name + " [" + image.getWidth(null) + "x" + image.getHeight(null) + "]");
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2002-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.samples.mtom.client.sws;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Driver {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Usage: java " + Driver.class.getName() + " filePath");
System.exit(-1);
}
String filePath = args[0];
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml", Driver.class);
SaajMtomClient saajClient = (SaajMtomClient) applicationContext.getBean("saajClient", SaajMtomClient.class);
saajClient.doIt(filePath);
AxiomMtomClient axiomClient =
(AxiomMtomClient) applicationContext.getBean("axiomClient", AxiomMtomClient.class);
axiomClient.doIt(filePath);
}
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright 2002-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.samples.mtom.client.sws;
import java.awt.Toolkit;
import java.io.File;
import javax.xml.bind.JAXBElement;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StopWatch;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.SoapFaultClientException;
/**
* Simple client that demonstartes MTOM by invoking <code>StoreImage</code> and <code>LoadImage</code> using a
* WebServiceTemplate.
*
* @author Tareq Abed Rabbo
*/
public class MtomClient extends WebServiceGatewaySupport {
public static void main(String[] args) {
try {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml", MtomClient.class);
MtomClient client = (MtomClient) applicationContext.getBean("mtomClient", MtomClient.class);
ObjectFactory objectFactory = new ObjectFactory();
Image image = objectFactory.createImage();
File file = new File(args[0]);
image.setName(file.getName());
image.setImage(Toolkit.getDefaultToolkit().getImage(args[0]));
JAXBElement<Image> storeImageRequest = objectFactory.createStoreImageRequest(image);
StopWatch stopWatch = new StopWatch();
stopWatch.start("store");
client.getWebServiceTemplate().marshalSendAndReceive(storeImageRequest);
stopWatch.stop();
JAXBElement<String> loadImageRequest = objectFactory.createLoadImageRequest(file.getName());
stopWatch.start("load");
Object result = client.getWebServiceTemplate().marshalSendAndReceive(loadImageRequest);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
}
catch (SoapFaultClientException ex) {
System.err.format("SOAP Fault Code %1s%n", ex.getFaultCode());
System.err.format("SOAP Fault String: %1s%n", ex.getFaultStringOrReason());
}
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2002-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.samples.mtom.client.sws;
import java.awt.Toolkit;
import javax.xml.bind.JAXBElement;
import org.springframework.util.ClassUtils;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.SoapFaultClientException;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
/**
* Simple client that demonstartes MTOM by invoking <code>StoreImage</code> and <code>LoadImage</code> using a
* WebServiceTemplate and SAAJ.
*
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
*/
public class SaajMtomClient extends WebServiceGatewaySupport {
private ObjectFactory objectFactory = new ObjectFactory();
private StopWatch stopWatch = new StopWatch(ClassUtils.getShortName(getClass()));
public SaajMtomClient(SaajSoapMessageFactory messageFactory) {
super(messageFactory);
}
public void doIt(String path) {
try {
store(path);
load(path);
System.out.println(stopWatch.prettyPrint());
}
catch (SoapFaultClientException ex) {
System.err.format("SOAP Fault Code %1s%n", ex.getFaultCode());
System.err.format("SOAP Fault String: %1s%n", ex.getFaultStringOrReason());
}
}
private void store(String path) {
Image image = objectFactory.createImage();
image.setName(StringUtils.getFilename(path));
image.setImage(Toolkit.getDefaultToolkit().getImage(path));
JAXBElement<Image> storeImageRequest = objectFactory.createStoreImageRequest(image);
stopWatch.start("store");
getWebServiceTemplate().marshalSendAndReceive(storeImageRequest);
stopWatch.stop();
}
private void load(String path) {
JAXBElement<String> loadImageRequest = objectFactory.createLoadImageRequest(StringUtils.getFilename(path));
stopWatch.start("load");
JAXBElement<Image> loadImageResponse =
(JAXBElement<Image>) getWebServiceTemplate().marshalSendAndReceive(loadImageRequest);
stopWatch.stop();
Image image = loadImageResponse.getValue();
logger.info("Received image " + image.getName() + " [" + image.getImage().getWidth(null) + "x" +
image.getImage().getHeight(null) + "]");
}
}

View File

@@ -2,8 +2,14 @@
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="mtomClient" class="org.springframework.ws.samples.mtom.client.sws.MtomClient">
<bean id="client" abstract="true">
<property name="defaultUri" value="http://localhost:8080/mtom/services"/>
</bean>
<bean id="saajClient" class="org.springframework.ws.samples.mtom.client.sws.SaajMtomClient" parent="client">
<constructor-arg>
<bean class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
</constructor-arg>
<property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="marshaller"/>
</bean>
@@ -13,4 +19,10 @@
<property name="mtomEnabled" value="true"/>
</bean>
<bean id="axiomClient" class="org.springframework.ws.samples.mtom.client.sws.AxiomMtomClient" parent="client">
<constructor-arg>
<bean class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory"/>
</constructor-arg>
</bean>
</beans>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2007 the original author or authors.
* Copyright 2002-2009 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.
@@ -32,12 +32,12 @@ public class StubImageRepository implements ImageRepository {
private Map<String, Image> images = new HashMap<String, Image>();
public Image readImage(String name) throws IOException {
logger.info("Streaming image " + name);
logger.info("Loading image " + name);
return images.get(name);
}
public void storeImage(String name, Image image) throws IOException {
logger.info("Storing image " + name);
logger.info("Storing image " + name + " [" + image.getWidth(null) + "x" + image.getHeight(null) + "]");
images.put(name, image);
}
}

View File

@@ -1,7 +1,5 @@
log4j.rootLogger=WARN, stdout
log4j.logger.org.springframework.ws=DEBUG
log4j.logger.org.springframework.oxm=DEBUG
log4j.logger.org.springframework.xml=DEBUG
log4j.logger.org.springframework.ws.samples=INFO
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout