Wiki source code of Web Services-Sending Large Data
Last modified by Pascal Robert on 2007/09/03 19:36
Hide last authors
author | version | line-number | content |
---|---|---|---|
![]() |
3.1 | 1 | === Kristoff Cossement === |
![]() |
1.1 | 2 | |
3 | Soap with mime attachments was indeed the way to go. | ||
4 | |||
![]() |
4.1 | 5 | Remark: this only works with java 1.4.2_09 (I did not get it working with java 1.5.x) |
![]() |
1.1 | 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. | ||
![]() |
4.1 | 8 | You also need the java mail and java activation framework from sun. |
![]() |
1.1 | 9 | |
![]() |
3.1 | 10 | ==== Client.java ==== |
![]() |
1.1 | 11 | |
![]() |
3.1 | 12 | {{code}} |
![]() |
1.1 | 13 | |
![]() |
3.1 | 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.*; | ||
![]() |
1.1 | 26 | |
![]() |
3.1 | 27 | public class Client { |
![]() |
1.1 | 28 | |
![]() |
3.1 | 29 | public static File resize(String sPath) |
30 | { | ||
31 | File file = new File(sPath); | ||
![]() |
1.1 | 32 | |
33 | |||
![]() |
3.1 | 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/"); | ||
![]() |
1.1 | 46 | |
![]() |
3.1 | 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()); | ||
![]() |
1.1 | 54 | |
![]() |
3.1 | 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(); | ||
![]() |
1.1 | 60 | |
![]() |
3.1 | 61 | if(!body.hasFault()) |
62 | { | ||
63 | System.out.println("answer : "+body); | ||
![]() |
1.1 | 64 | |
![]() |
3.1 | 65 | } |
66 | } | ||
67 | catch(Exception e) | ||
68 | { | ||
69 | e.printStackTrace(); | ||
70 | } | ||
71 | return null; | ||
72 | } | ||
![]() |
1.1 | 73 | |
![]() |
3.1 | 74 | public static void main(String[] args) { |
![]() |
1.1 | 75 | |
![]() |
3.1 | 76 | try { |
![]() |
1.1 | 77 | |
![]() |
3.1 | 78 | resize(args[0]); |
79 | |||
80 | } | ||
81 | catch (Exception e) { | ||
82 | System.out.println(e.getMessage()); | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | |||
87 | {{/code}} | ||
88 | |||
89 | ===== Webobjects Application .java ===== | ||
90 | |||
91 | override dispatchRequest | ||
92 | |||
93 | {{code}} | ||
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 | {{/code}} | ||
127 | |||
128 | ===== Dispatcher.java ===== | ||
129 | |||
130 | {{code}} | ||
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 | {{/code}} |