Wiki source code of Programming__WebObjects-Web Services-Sending Large Data
Version 1.1 by smmccraw on 2007/07/08 09:46
Show last authors
| author | version | line-number | content |
|---|---|---|---|
| 1 | === Kristoff Cossement === | ||
| 2 | |||
| 3 | Soap with mime attachments was indeed the way to go. | ||
| 4 | |||
| 5 | Remark: this only works with java 1.4.2//09 (I did not get it working with java 1.5.x)// | ||
| 6 | |||
| 7 | 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. | ||
| 8 | You also need the java mail and java activation framework from sun. | ||
| 9 | |||
| 10 | ==== Client.java ==== | ||
| 11 | |||
| 12 | {{panel}} | ||
| 13 | |||
| 14 | import javax.xml.soap.SOAPConnectionFactory; | ||
| 15 | import javax.xml.soap.*; | ||
| 16 | import javax.xml.transform.stream.*; | ||
| 17 | import javax.xml.transform.*; | ||
| 18 | import java.io.*; | ||
| 19 | import org.apache.axis.attachments.AttachmentPart; | ||
| 20 | import org.apache.axis.message.*; | ||
| 21 | import javax.activation.DataHandler; | ||
| 22 | import javax.activation.FileDataSource; | ||
| 23 | import javax.xml.soap.SOAPElement; | ||
| 24 | import java.util.*; | ||
| 25 | import javax.mail.*; | ||
| 26 | |||
| 27 | public class Client { | ||
| 28 | |||
| 29 | public static File resize(String sPath) | ||
| 30 | { | ||
| 31 | File file = new File(sPath); | ||
| 32 | |||
| 33 | |||
| 34 | String endPoint = "http://localhost:55555/cgi-bin/WebObjects/project.woa/ws/FileUpload"; | ||
| 35 | try{ | ||
| 36 | SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection(); | ||
| 37 | SOAPMessage message = (javax.xml.soap.SOAPMessage)MessageFactory.newInstance().createMessage(); | ||
| 38 | SOAPPart part = message.getSOAPPart(); | ||
| 39 | SOAPEnvelope envelope = (org.apache.axis.message.SOAPEnvelope)part.getEnvelope(); | ||
| 40 | SOAPBody body = (org.apache.axis.message.SOAPBody)envelope.getBody(); | ||
| 41 | SOAPBodyElement operation = (org.apache.axis.message.SOAPBodyElement)body.addBodyElement( | ||
| 42 | envelope.createName("upload", | ||
| 43 | "ns", | ||
| 44 | "http://localhost:55555/cgi-bin/WebObjects/project.woa/ws/FileUpload")); | ||
| 45 | operation.setEncodingStyle("http://schemas.xmlsoaporg/soap/encoding/"); | ||
| 46 | |||
| 47 | DataHandler dh = new DataHandler(new FileDataSource(file)); | ||
| 48 | AttachmentPart attachment = (org.apache.axis.attachments.AttachmentPart)message.createAttachmentPart(dh); | ||
| 49 | SOAPElement filename = operation.addChildElement("filename",""); | ||
| 50 | SOAPElement source = operation.addChildElement("source",""); | ||
| 51 | message.addAttachmentPart(attachment); | ||
| 52 | filename.addTextNode(file.getName()); | ||
| 53 | source.addTextNode(attachment.getContentId()); | ||
| 54 | |||
| 55 | SOAPMessage result = connection.call(message,endPoint); | ||
| 56 | System.out.println(result); | ||
| 57 | part = result.getSOAPPart(); | ||
| 58 | envelope = (org.apache.axis.message.SOAPEnvelope)part.getEnvelope(); | ||
| 59 | body = (org.apache.axis.message.SOAPBody)envelope.getBody(); | ||
| 60 | |||
| 61 | if(!body.hasFault()) | ||
| 62 | ________{ | ||
| 63 | __________System.out.println("answer_:_"+body); | ||
| 64 | __ | ||
| 65 | ________} | ||
| 66 | ______} | ||
| 67 | ______catch(Exception_e) | ||
| 68 | ______{ | ||
| 69 | ________e.printStackTrace(); | ||
| 70 | ______} | ||
| 71 | ______return_null; | ||
| 72 | ____} | ||
| 73 | __ | ||
| 74 | ____public_static_void_main(String[]_args)_{ | ||
| 75 | __ | ||
| 76 | ______try_{ | ||
| 77 | __ | ||
| 78 | ________resize(args[0]); | ||
| 79 | __ | ||
| 80 | ______} | ||
| 81 | ______catch_(Exception_e)_{ | ||
| 82 | ________System.out.println(e.getMessage()); | ||
| 83 | ______} | ||
| 84 | ____} | ||
| 85 | __} | ||
| 86 | |||
| 87 | {{/panel}} | ||
| 88 | |||
| 89 | ==== Webobjects//Application//.java ==== | ||
| 90 | |||
| 91 | override//dispatchRequest// | ||
| 92 | |||
| 93 | {{panel}} | ||
| 94 | |||
| 95 | __public_WOResponse_dispatchRequest(WORequest_request) | ||
| 96 | __{ | ||
| 97 | ____WOResponse_result_=_null; | ||
| 98 | ____String_sURI_=_request.uri(); | ||
| 99 | ____NSLog.debug.appendln("Accessing_"_+_sURI); | ||
| 100 | __ | ||
| 101 | ____Pattern_p_=_Pattern.compile("/ws/FileUpload"); | ||
| 102 | ____Matcher_m_=_p.matcher(sURI); | ||
| 103 | ____if(m.find()) | ||
| 104 | ____{ | ||
| 105 | ______String_sContType_=_request.headerForKey("content-type"); | ||
| 106 | ______p_=_Pattern.compile("multipart/related"); | ||
| 107 | ______m_=_p.matcher(sContType); | ||
| 108 | ______if(m.find()) | ||
| 109 | ______{ | ||
| 110 | ________result_=_Dispatcher.handleFileUpload(request); | ||
| 111 | ______} | ||
| 112 | ______else | ||
| 113 | ______{ | ||
| 114 | ________result_=_super.dispatchRequest(request); | ||
| 115 | ______} | ||
| 116 | ____} | ||
| 117 | ____else | ||
| 118 | ____{ | ||
| 119 | ______result_=_super.dispatchRequest(request); | ||
| 120 | ____} | ||
| 121 | __ | ||
| 122 | ____return_result; | ||
| 123 | __ | ||
| 124 | __} | ||
| 125 | |||
| 126 | {{/panel}} | ||
| 127 | |||
| 128 | ==== Dispatcher.java ==== | ||
| 129 | |||
| 130 | {{panel}} | ||
| 131 | |||
| 132 | __// | ||
| 133 | __//_Dispatcher.java | ||
| 134 | __//_project | ||
| 135 | __// | ||
| 136 | __//_Created_by_admin_on_5/5/06. | ||
| 137 | __//_Copyright_2006___MyCompanyName__._All_rights_reserved. | ||
| 138 | __// | ||
| 139 | __import_com.webobjects.foundation.*; | ||
| 140 | __import_com.webobjects.appserver.*; | ||
| 141 | __import_com.webobjects.eocontrol.*; | ||
| 142 | __ | ||
| 143 | __import_java.io.*; | ||
| 144 | __import_java.util.regex.*; | ||
| 145 | __import_org.w3c.dom.*; | ||
| 146 | __import_javax.xml.transform.*; | ||
| 147 | __import_javax.xml.transform.stream.*; | ||
| 148 | __import_javax.xml.transform.dom.*; | ||
| 149 | __import_javax.xml.parsers.*; | ||
| 150 | __import_org.apache.axis.attachments.*; | ||
| 151 | __ | ||
| 152 | __ | ||
| 153 | __public_class_Dispatcher_{ | ||
| 154 | __ | ||
| 155 | ____public_static_WOResponse_handleFileUpload(WORequest_request) | ||
| 156 | ____{ | ||
| 157 | ______String_sContType_=_request.headerForKey("content-type"); | ||
| 158 | ______String_sSoapXml_=_""; | ||
| 159 | ______InputStream_requestStream_=_request.contentInputStream(); | ||
| 160 | __ | ||
| 161 | ______String_sTempDir_=_System.getProperty("java.io.tmpdir"); | ||
| 162 | ______String_timestamp_=(new_Long(System.currentTimeMillis())).toString(); | ||
| 163 | ______File_fTempFile_=_new_File(sTempDir+"/"+timestamp); | ||
| 164 | ______File_fSavedFile_=_new_File(sTempDir+"/"+timestamp+".out"); | ||
| 165 | __ | ||
| 166 | ______try | ||
| 167 | ______{ | ||
| 168 | ________BufferedOutputStream_fOut_=_new_BufferedOutputStream(new_FileOutputStream(fTempFile)); | ||
| 169 | ________byte[)_buffer_=_new_byte(32_*_1024]; | ||
| 170 | ________int_bytesRead_=_0; | ||
| 171 | ________while_((bytesRead_=_requestStream.read(buffer))_!= -1) | ||
| 172 | { | ||
| 173 | fOut.write(buffer, 0, bytesRead); | ||
| 174 | } | ||
| 175 | fOut.close(); | ||
| 176 | } | ||
| 177 | catch (Exception e) | ||
| 178 | { | ||
| 179 | NSLog.debug.appendln(e.getMessage()); | ||
| 180 | } | ||
| 181 | |||
| 182 | try | ||
| 183 | { | ||
| 184 | InputStream iStream = new FileInputStream(fTempFile); | ||
| 185 | |||
| 186 | MultiPartRelatedInputStream mis = new MultiPartRelatedInputStream(sContType,iStream); | ||
| 187 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | ||
| 188 | Document doc = factory.newDocumentBuilder().parse(mis); | ||
| 189 | sSoapXml = toString(doc); | ||
| 190 | NSLog.debug.appendln("SOAP Envelope: " + sSoapXml); | ||
| 191 | mis.close(); | ||
| 192 | iStream.close(); | ||
| 193 | |||
| 194 | Node nEnvelope = getNamedChildNode(doc,"Envelope"); | ||
| 195 | if(null !=_nEnvelope) | ||
| 196 | ________{ | ||
| 197 | __________Node_nBody_=_getNamedChildNode(nEnvelope,"Body"); | ||
| 198 | __________if(null_!= nBody) | ||
| 199 | { | ||
| 200 | NSArray nSubNodes = getElementChildNodes(nBody); | ||
| 201 | if((null !=_nSubNodes)_&&_(nSubNodes.count()_>_0)) | ||
| 202 | ____________{ | ||
| 203 | ______________Node_nFileUpload_=_(Node)nSubNodes.get(0); | ||
| 204 | ______________nSubNodes_=_getElementChildNodes(nFileUpload); | ||
| 205 | ______________if((null_!= nSubNodes) && (nSubNodes.count() > 1)) | ||
| 206 | { | ||
| 207 | Node nFileName = (Node)nSubNodes.get(0); | ||
| 208 | Node nData = (Node)nSubNodes.get(1); | ||
| 209 | |||
| 210 | String sFileName = getTextFromNode(nFileName); | ||
| 211 | String sFileMimeID = getTextFromNode(nData); | ||
| 212 | |||
| 213 | fSavedFile = new File(sTempDir+"/"+sFileName); | ||
| 214 | |||
| 215 | Pattern pattern = Pattern.compile("(boundary=\".+?\")"); | ||
| 216 | Matcher match = pattern.matcher(sContType); | ||
| 217 | if(match.find()) | ||
| 218 | { | ||
| 219 | String boundary= match.group(1); | ||
| 220 | String sSubContentType = "multipart/related; type=\"text/xml\"; start=\"<"+sFileMimeID+">\"; "+boundary; | ||
| 221 | iStream = new FileInputStream(fTempFile); | ||
| 222 | mis = new MultiPartRelatedInputStream(sSubContentType,iStream); | ||
| 223 | try | ||
| 224 | { | ||
| 225 | BufferedOutputStream fOut = new BufferedOutputStream(new FileOutputStream(fSavedFile)); | ||
| 226 | byte[) buffer = new byte(32 * 1024]; | ||
| 227 | int bytesRead = 0; | ||
| 228 | while ((bytesRead = mis.read(buffer)) !=_-1) | ||
| 229 | ____________________{ | ||
| 230 | ______________________fOut.write(buffer,_0,_bytesRead); | ||
| 231 | ____________________} | ||
| 232 | ____________________mis.close(); | ||
| 233 | ____________________fOut.close(); | ||
| 234 | __________________} | ||
| 235 | __________________catch_(Exception_e) | ||
| 236 | __________________{ | ||
| 237 | ____________________System.out.println(e.getMessage()); | ||
| 238 | ____________________//throw_new_IOException(me_+_"_failed,_got:_"_+_e.toString()); | ||
| 239 | __________________} | ||
| 240 | ________________} | ||
| 241 | ______________} | ||
| 242 | ____________}__ | ||
| 243 | __________} | ||
| 244 | ________} | ||
| 245 | ______} | ||
| 246 | ______catch(Exception_e) | ||
| 247 | ______{ | ||
| 248 | ________e.printStackTrace(); | ||
| 249 | ______} | ||
| 250 | __ | ||
| 251 | __ | ||
| 252 | ______WOResponse_result_=_new_WOResponse(); | ||
| 253 | ______result.setContent(_"<?xml_version="1.0"_encoding="UTF-8"?>n"+ | ||
| 254 | __________"<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"+ | ||
| 255 | __________"<soapenv:Body>n"+ | ||
| 256 | __________"<ns:uploadResponse_soapenv:encodingStyle="http://schemas.xmlsoaporg/soap/encoding/"_xmlns:ns="http://localhost:55555/cgi-bin/WebObjects/project.woa/ws/FileUpload">n"+ | ||
| 257 | __________"<ns:uploadReturn_xsi:type="xsd:boolean">true</ns:uploadReturn>n"+ | ||
| 258 | __________"</ns:uploadResponse>n"+ | ||
| 259 | __________"</soapenv:Body>n"+ | ||
| 260 | __________"</soapenv:Envelope>"); | ||
| 261 | __ | ||
| 262 | __ | ||
| 263 | ______result.setHeader("text/xml;_charset=utf-8","content-type"); | ||
| 264 | __ | ||
| 265 | __ | ||
| 266 | ______return_result; | ||
| 267 | __ | ||
| 268 | ____} | ||
| 269 | __ | ||
| 270 | __ | ||
| 271 | ____static_public_String_toString(Document_document)_{ | ||
| 272 | ______String_result_=_null; | ||
| 273 | __ | ||
| 274 | ______if_(document_!= null) { | ||
| 275 | StringWriter strWtr = new StringWriter(); | ||
| 276 | StreamResult strResult = new StreamResult(strWtr); | ||
| 277 | TransformerFactory tfac = TransformerFactory.newInstance(); | ||
| 278 | try { | ||
| 279 | Transformer t = tfac.newTransformer(); | ||
| 280 | t.setOutputProperty(OutputKeys.ENCODING, "utf-8"); | ||
| 281 | t.setOutputProperty(OutputKeys.INDENT, "yes"); | ||
| 282 | t.setOutputProperty(OutputKeys.METHOD, "xml"); //xml, html, text | ||
| 283 | t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); | ||
| 284 | t.transform(new DOMSource(document.getDocumentElement()), strResult); | ||
| 285 | } catch (Exception e) { | ||
| 286 | System.err.println("XML.toString(Document): " + e); | ||
| 287 | } | ||
| 288 | result = strResult.getWriter().toString(); | ||
| 289 | } | ||
| 290 | |||
| 291 | return result; | ||
| 292 | } | ||
| 293 | |||
| 294 | static public Node getNamedChildNode(Node n, String sChildNodeName) | ||
| 295 | { | ||
| 296 | |||
| 297 | NodeList nl = n.getChildNodes(); | ||
| 298 | |||
| 299 | for(int i=0;i<nl.getLength();i++) | ||
| 300 | { | ||
| 301 | Node s = nl.item(i); | ||
| 302 | String sChild = s.getNodeName(); | ||
| 303 | if(sChildNodeName.equalsIgnoreCase(sChild) || sChild.endsWith(":"+sChildNodeName)) | ||
| 304 | { | ||
| 305 | NSLog.debug.appendln("childnode = " + s.getNodeName()); | ||
| 306 | return s; | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | return null; | ||
| 311 | |||
| 312 | } | ||
| 313 | static public NSArray getElementChildNodes(Node n) | ||
| 314 | { | ||
| 315 | NSMutableArray elements = new NSMutableArray(); | ||
| 316 | NodeList nl = n.getChildNodes(); | ||
| 317 | |||
| 318 | for(int i=0;i<nl.getLength();i++) | ||
| 319 | { | ||
| 320 | Node s = nl.item(i); | ||
| 321 | if(s.getNodeType() == Node.ELEMENT_NODE) | ||
| 322 | { | ||
| 323 | NSLog.debug.appendln("childnode = " + s.getNodeName()); | ||
| 324 | elements.addObject(s); | ||
| 325 | } | ||
| 326 | } | ||
| 327 | |||
| 328 | return elements; | ||
| 329 | } | ||
| 330 | static public String getTextFromNode(Node n) | ||
| 331 | { | ||
| 332 | String text = ""; | ||
| 333 | |||
| 334 | NodeList nl = n.getChildNodes(); | ||
| 335 | |||
| 336 | for(int i=0;i<nl.getLength();i++) | ||
| 337 | { | ||
| 338 | Node s = nl.item(i); | ||
| 339 | if(s.getNodeType() == Node.TEXT_NODE) | ||
| 340 | { | ||
| 341 | return s.getNodeValue(); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | return text; | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | {{/panel}} | ||
| 349 | |||
| 350 | Category:WebObjects |