Web Services-Sending Large Data
Version 5.1 by Pascal Robert on 2007/09/03 19:36
Kristoff Cossement
Soap with mime attachments was indeed the way to go.
Remark: this only works with java 1.4.2_09 (I did not get it working with java 1.5.x)
For those who are interested I included some sample code on how to exchange large binary data between a java client and and webobjects server without taking all data in memory.
You also need the java mail and java activation framework from sun.
Client.java
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.*;
import java.io.*;
import org.apache.axis.attachments.AttachmentPart;
import org.apache.axis.message.*;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.soap.SOAPElement;
import java.util.*;
import javax.mail.*;
public class Client {
public static File resize(String sPath)
{
File file = new File(sPath);
String endPoint = "http://localhost:55555/cgi-bin/WebObjects/project.woa/ws/FileUpload";
try{
SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
SOAPMessage message = (javax.xml.soap.SOAPMessage)MessageFactory.newInstance().createMessage();
SOAPPart part = message.getSOAPPart();
SOAPEnvelope envelope = (org.apache.axis.message.SOAPEnvelope)part.getEnvelope();
SOAPBody body = (org.apache.axis.message.SOAPBody)envelope.getBody();
SOAPBodyElement operation = (org.apache.axis.message.SOAPBodyElement)body.addBodyElement(
envelope.createName("upload",
"ns",
"http://localhost:55555/cgi-bin/WebObjects/project.woa/ws/FileUpload"));
operation.setEncodingStyle("http://schemas.xmlsoaporg/soap/encoding/");
DataHandler dh = new DataHandler(new FileDataSource(file));
AttachmentPart attachment = (org.apache.axis.attachments.AttachmentPart)message.createAttachmentPart(dh);
SOAPElement filename = operation.addChildElement("filename","");
SOAPElement source = operation.addChildElement("source","");
message.addAttachmentPart(attachment);
filename.addTextNode(file.getName());
source.addTextNode(attachment.getContentId());
SOAPMessage result = connection.call(message,endPoint);
System.out.println(result);
part = result.getSOAPPart();
envelope = (org.apache.axis.message.SOAPEnvelope)part.getEnvelope();
body = (org.apache.axis.message.SOAPBody)envelope.getBody();
if(!body.hasFault())
{
System.out.println("answer : "+body);
}
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
try {
resize(args[0]);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Webobjects Application .java
override dispatchRequest
public WOResponse dispatchRequest(WORequest request)
{
WOResponse result = null;
String sURI = request.uri();
NSLog.debug.appendln("Accessing " + sURI);
Pattern p = Pattern.compile("/ws/FileUpload");
Matcher m = p.matcher(sURI);
if(m.find())
{
String sContType = request.headerForKey("content-type");
p = Pattern.compile("multipart/related");
m = p.matcher(sContType);
if(m.find())
{
result = Dispatcher.handleFileUpload(request);
}
else
{
result = super.dispatchRequest(request);
}
}
else
{
result = super.dispatchRequest(request);
}
return result;
}
Dispatcher.java
//
// Dispatcher.java
// project
//
// Created by admin on 5/5/06.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//
import com.webobjects.foundation.*;
import com.webobjects.appserver.*;
import com.webobjects.eocontrol.*;
import java.io.*;
import java.util.regex.*;
import org.w3c.dom.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import javax.xml.parsers.*;
import org.apache.axis.attachments.*;
public class Dispatcher {
public static WOResponse handleFileUpload(WORequest request)
{
String sContType = request.headerForKey("content-type");
String sSoapXml = "";
InputStream requestStream = request.contentInputStream();
String sTempDir = System.getProperty("java.io.tmpdir");
String timestamp =(new Long(System.currentTimeMillis())).toString();
File fTempFile = new File(sTempDir+"/"+timestamp);
File fSavedFile = new File(sTempDir+"/"+timestamp+".out");
try
{
BufferedOutputStream fOut = new BufferedOutputStream(new FileOutputStream(fTempFile));
byte[] buffer = new byte[32 * 1024];
int bytesRead = 0;
while ((bytesRead = requestStream.read(buffer)) != -1)
{
fOut.write(buffer, 0, bytesRead);
}
fOut.close();
}
catch (Exception e)
{
NSLog.debug.appendln(e.getMessage());
}
try
{
InputStream iStream = new FileInputStream(fTempFile);
MultiPartRelatedInputStream mis = new MultiPartRelatedInputStream(sContType,iStream);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().parse(mis);
sSoapXml = toString(doc);
NSLog.debug.appendln("SOAP Envelope: " + sSoapXml);
mis.close();
iStream.close();
Node nEnvelope = getNamedChildNode(doc,"Envelope");
if(null != nEnvelope)
{
Node nBody = getNamedChildNode(nEnvelope,"Body");
if(null != nBody)
{
NSArray nSubNodes = getElementChildNodes(nBody);
if((null != nSubNodes) && (nSubNodes.count() > 0))
{
Node nFileUpload = (Node)nSubNodes.get(0);
nSubNodes = getElementChildNodes(nFileUpload);
if((null != nSubNodes) && (nSubNodes.count() > 1))
{
Node nFileName = (Node)nSubNodes.get(0);
Node nData = (Node)nSubNodes.get(1);
String sFileName = getTextFromNode(nFileName);
String sFileMimeID = getTextFromNode(nData);
fSavedFile = new File(sTempDir+"/"+sFileName);
Pattern pattern = Pattern.compile("(boundary=\".+?\")");
Matcher match = pattern.matcher(sContType);
if(match.find())
{
String boundary= match.group(1);
String sSubContentType = "multipart/related; type=\"text/xml\"; start=\"<"+sFileMimeID+">\"; "+boundary;
iStream = new FileInputStream(fTempFile);
mis = new MultiPartRelatedInputStream(sSubContentType,iStream);
try
{
BufferedOutputStream fOut = new BufferedOutputStream(new FileOutputStream(fSavedFile));
byte[] buffer = new byte[32 * 1024];
int bytesRead = 0;
while ((bytesRead = mis.read(buffer)) != -1)
{
fOut.write(buffer, 0, bytesRead);
}
mis.close();
fOut.close();
}
catch (Exception e)
{
System.out.println(e.getMessage());
//throw new IOException(me + " failed, got: " + e.toString());
}
}
}
}
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
WOResponse result = new WOResponse();
result.setContent( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoaporg/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"+
"<soapenv:Body>\n"+
"<ns:uploadResponse soapenv:encodingStyle=\"http://schemas.xmlsoaporg/soap/encoding/\" xmlns:ns=\"http://localhost:55555/cgi-bin/WebObjects/project.woa/ws/FileUpload\">\n"+
"<ns:uploadReturn xsi:type=\"xsd:boolean\">true</ns:uploadReturn>\n"+
"</ns:uploadResponse>\n"+
"</soapenv:Body>\n"+
"</soapenv:Envelope>");
result.setHeader("text/xml; charset=utf-8","content-type");
return result;
}
static public String toString(Document document) {
String result = null;
if (document != null) {
StringWriter strWtr = new StringWriter();
StreamResult strResult = new StreamResult(strWtr);
TransformerFactory tfac = TransformerFactory.newInstance();
try {
Transformer t = tfac.newTransformer();
t.setOutputProperty(OutputKeys.ENCODING, "utf-8");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty(OutputKeys.METHOD, "xml"); //xml, html, text
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
t.transform(new DOMSource(document.getDocumentElement()), strResult);
} catch (Exception e) {
System.err.println("XML.toString(Document): " + e);
}
result = strResult.getWriter().toString();
}
return result;
}
static public Node getNamedChildNode(Node n, String sChildNodeName)
{
NodeList nl = n.getChildNodes();
for(int i=0;i<nl.getLength();i++)
{
Node s = nl.item(i);
String sChild = s.getNodeName();
if(sChildNodeName.equalsIgnoreCase(sChild) || sChild.endsWith(":"+sChildNodeName))
{
NSLog.debug.appendln("childnode = " + s.getNodeName());
return s;
}
}
return null;
}
static public NSArray getElementChildNodes(Node n)
{
NSMutableArray elements = new NSMutableArray();
NodeList nl = n.getChildNodes();
for(int i=0;i<nl.getLength();i++)
{
Node s = nl.item(i);
if(s.getNodeType() == Node.ELEMENT_NODE)
{
NSLog.debug.appendln("childnode = " + s.getNodeName());
elements.addObject(s);
}
}
return elements;
}
static public String getTextFromNode(Node n)
{
String text = "";
NodeList nl = n.getChildNodes();
for(int i=0;i<nl.getLength();i++)
{
Node s = nl.item(i);
if(s.getNodeType() == Node.TEXT_NODE)
{
return s.getNodeValue();
}
}
return text;
}
}