I was part of a team that did a Proof of Concept (PoC) to demonstrate the capabilities of Java CAPS at a prospective customer recently. One of the requirements of the PoC was to handle SOAP (1.1) with Attachments (SwA) from within Java CAPS. I searched high and low for an example. I was fortunate enough to find none...
I figured that the SOAP with Attachments API for Java (SAAJ) would be a good place to start. I looked through the API documentation and found that I will need a byte array and the SOAP message's MIME headers to create a SOAP message using SAAJ. All I needed to do was to expose the HTTPServer's processRequest as a JCD.
Here is the implementation:
001 package SOAP_1_u002E_1SOAP_With_Attachments_SAAJ_452723634; 002 003 004 import java.io.BufferedInputStream; 005 import java.io.ByteArrayInputStream; 006 import java.io.ByteArrayOutputStream; 007 import java.io.IOException; 008 import java.io.LineNumberReader; 009 import java.io.StringReader; 010 import java.util.Iterator; 011 012 import javax.xml.soap.AttachmentPart; 013 import javax.xml.soap.MessageFactory; 014 import javax.xml.soap.MimeHeaders; 015 import javax.xml.soap.Name; 016 import javax.xml.soap.SOAPElement; 017 import javax.xml.soap.SOAPException; 018 import javax.xml.soap.SOAPFactory; 019 import javax.xml.soap.SOAPMessage; 020 021 import org.w3c.dom.Node; 022 023 import com.stc.codegen.alerter.Alerter; 024 import com.stc.codegen.logger.Logger; 025 import com.stc.codegen.util.CollaborationContext; 026 import com.stc.codegen.util.TypeConverter; 027 import com.stc.connector.otd.httpserveradapter.webservice.WebHeaderList; 028 import com.stc.connector.otd.httpserveradapter.webservice.WebServerApplication; 029 030 031 public class jcdSwAWithSAAJ13 { 032 public Logger logger; 033 034 public Alerter alerter; 035 036 public CollaborationContext collabContext; 037 038 public TypeConverter typeConverter; 039 040 public void processRequest(final WebServerApplication input) 041 throws Throwable { 042 MessageFactory mf_ = MessageFactory.newInstance(); 043 SOAPMessage message_ = unmarshalSOAPMessage(input, mf_); 044 int helloIndexValue_ = 0; 045 int worldIndexValue_ = 0; 046 if (null != message_) { 047 helloIndexValue_ = extractIndex("helloIndex", message_); 048 worldIndexValue_ = extractIndex("worldIndex", message_); 049 } 050 051 String greeting_ = buildGreeting( 052 helloIndexValue_, worldIndexValue_, message_); 053 SOAPMessage response_ = generateResponse(mf_, greeting_); 054 if (null != response_) { 055 sendResponse(response_, input); 056 } 057 } 058 059 private SOAPMessage unmarshalSOAPMessage( 060 final WebServerApplication input, final MessageFactory factory) { 061 SOAPMessage result_ = null; 062 try { 063 BufferedInputStream bis_ = new BufferedInputStream( 064 new ByteArrayInputStream(input.getRequest().getByteArray())); 065 MimeHeaders headers_ = extractHeaders( 066 input.getRequest().getHeaderInfo()); 067 result_ = factory.createMessage(headers_, bis_); 068 } catch (Exception e_) { 069 error(e_.getMessage(), e_.getCause()); 070 } 071 072 return result_; 073 } 074 075 private int extractIndex( 076 final String indexName, final SOAPMessage message) { 077 int result_ = Integer.MIN_VALUE; 078 SOAPElement element_ = extractElement(indexName, message); 079 if (null != element_) { 080 result_ = typeConverter.stringToInt( 081 element_.getValue(), "#", false, 0); 082 } else { 083 result_ = 1; 084 } 085 086 return result_; 087 } 088 089 private String buildGreeting( 090 final int helloIndex, final int worldIndex, 091 final SOAPMessage message) { 092 String result_ = ""; 093 094 Iterator attachments_ = message.getAttachments(); 095 int numberOfAttachments_ = 0; 096 String hello_ = ""; 097 String world_ = ""; 098 while (attachments_.hasNext()) { 099 numberOfAttachments_++; 100 AttachmentPart attachment_ = (AttachmentPart) attachments_.next(); 101 if (attachment_.getContentId().equalsIgnoreCase( 102 "hello_in_multiple_languages")) { 103 hello_ = extractWord(attachment_, helloIndex); 104 } else if (attachment_.getContentId().equalsIgnoreCase( 105 "world_in_multiple_languages")) { 106 world_ = extractWord(attachment_, worldIndex); 107 } 108 } 109 110 result_ = hello_ + " " + world_ + "!"; 111 112 return result_; 113 } 114 115 /** Dito */ 116 private MimeHeaders extractHeaders(final WebHeaderList headers) { 117 MimeHeaders result_ = new MimeHeaders(); 118 int numberOfHeaders_ = headers.countWebHeaderList(); 119 for ( 120 int headerIndex_ = 0; 121 headerIndex_ < numberOfHeaders_; 122 headerIndex_++) { 123 String headerName_ = headers.getWebHeaderList( 124 headerIndex_).getName(); 125 String[] headerValues_ = headers.getWebHeaderList( 126 headerIndex_).getValues(); 127 for ( 128 int headerValueIndex_ = 0; 129 headerValueIndex_ < headerValues_.length; 130 headerValueIndex_++) { 131 result_.addHeader( 132 headerName_, headerValues_[headerValueIndex_]); 133 } 134 } 135 136 return result_; 137 } 138 139 private SOAPElement extractElement(final String localName, 140 final SOAPMessage message) { 141 SOAPElement element_ = null; 142 143 try { 144 Iterator elements_ = message.getSOAPBody().getChildElements(); 145 while (elements_.hasNext()) { 146 Node n_ = (Node) elements_.next(); 147 if (n_.getLocalName().equalsIgnoreCase(localName)) { 148 element_ = (SOAPElement) n_; 149 break; 150 } 151 } 152 } catch (Exception e_) { 153 error(e_.getMessage(), e_.getCause()); 154 } 155 156 return element_; 157 } 158 159 private String extractWord(final AttachmentPart attachment, 160 final int index) { 161 String result_ = "Yebo"; 162 163 try { 164 LineNumberReader reader_ = new LineNumberReader( 165 new StringReader((String) attachment.getContent())); 166 int escapeHatch_ = 0; 167 while (reader_.getLineNumber() < index) { 168 result_ = reader_.readLine(); 169 if (escapeHatch_++ > index) { 170 break; 171 } 172 } 173 } catch (Exception e_) { 174 error(e_.getMessage(), e_.getCause()); 175 } 176 177 return result_; 178 } 179 180 private SOAPMessage generateResponse(final MessageFactory factory, 181 final String greeting) { 182 SOAPMessage response_ = null; 183 184 try { 185 response_ = factory.createMessage(); 186 SOAPFactory factory_ = SOAPFactory.newInstance(); 187 Name helloWorldName_ = factory_.createName( 188 "helloWorld", "dhpoc", "http://www.discovery.co.za/poc"); 189 response_.getSOAPBody().addBodyElement(helloWorldName_).setValue( 190 greeting); 191 } catch (SOAPException e_) { 192 error(e_.getMessage(), e_.getCause()); 193 } 194 195 return response_; 196 } 197 198 private void sendResponse(final SOAPMessage response, 199 final WebServerApplication input) { 200 try { 201 byte[] responseAsBytes_ = convertResponseToBytes(response); 202 if (responseAsBytes_.length > 0) { 203 input.getResponse().setByteArray(responseAsBytes_); 204 input.getResponse().setContentType("text/xml"); 205 input.getResponse().setContentLength( 206 input.getResponse().getByteArray().length); 207 input.sendResponse(); 208 } 209 } catch (Exception e_) { 210 error(e_.getMessage(), e_.getCause()); 211 } 212 } 213 214 private byte[] convertResponseToBytes(final SOAPMessage message) { 215 ByteArrayOutputStream baos_ = new ByteArrayOutputStream(); 216 try { 217 message.writeTo(baos_); 218 } catch (SOAPException e_) { 219 error(e_.getMessage(), e_.getCause()); 220 } catch (IOException e_) { 221 error(e_.getMessage(), e_.getCause()); 222 } 223 224 return baos_.toByteArray(); 225 } 226 private void error(final String message, final Throwable t) { 227 logger.error("::: ::: " + message + " ::: :::", t); 228 } 229 }
|
unmarshallSOAPMessage on line 59 shows how to reconstruct the incoming SOAP message from the WebApplication's byte array and HeaderList. The rest is fairly obvious. sendResponse on line 198 shows how to pump a newly created SOAP message back over the wire.
That covers SwA server functionality within Java CAPS. I will show the client side code in a next blog.