是一个saaj的例子,SOAP with Attachments API for Java就是说用message传输附件。附件可以是图片,音频,视频等。但saaj是一个低级别的api,需要你自己创建和组装message。比较麻烦,下面有个例子供大家参考一下.
不好意思,下面的代码没法看。以下的内容都是引用自Java Web Services in a Nutshell.chm
可以通过我的资源中得到,不过是E文。
需要的包:
saaj-api.jar | saaj-ri.jar | activation.jar | commons-logging.jar |
dom4j.jar | mail.jar | jaxp-api.jar | dom.jar |
sax.jar | xalan.jar | xercesImpl.jar | xsltc.jar |
To run a SAAJ client application with J2EE 1.4, your CLASSPATH needs to include lib/j2ee.jar, together with the following four files from the endorsed directory:
dom.jar | sax.jar | xalan.jar | xercesImpl.jar |
message的结构图:
服务器端代码:BookImageServlet.java,BookImageServletData.java,booklist.txt,SAAJServlet.java。同时在booklist.txt建一个images文件夹,放些图片进去,文件名参考该文件。
package ora.jwsnut.saaj; import java.io.IOException; import java.io.OutputStream; import java.util.Enumeration; import java.util.Iterator; import java.util.StringTokenizer; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.soap.MessageFactory; import javax.xml.soap.MimeHeader; import javax.xml.soap.MimeHeaders; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage;
/** * A servlet that can be used to host a SAAJ * service within a web container. This is based * on ReceivingServlet.java in the JWSDP tutorial * examples. */ public abstract class SAAJServlet extends HttpServlet { /** * The factory used to build messages */ protected MessageFactory messageFactory; /** * Initialisation - create the MessageFactory */ public void init(ServletConfig config) throws ServletException { super.init(config); try { messageFactory = MessageFactory.newInstance(); } catch (SOAPException ex) { throw new ServletException("Failed to create MessageFactory", ex); } } /** * Handles a POST request from a client. The request is assumed * to contain a SOAP message with the HTTP binding. */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // Get all the HTTP headers and convert them to a MimeHeaders object MimeHeaders mimeHeaders = getMIMEHeaders(request);
// Create a SOAPMessage from the content of the HTTP request SOAPMessage message = messageFactory.createMessage(mimeHeaders, request.getInputStream()); // Let the subclass handle the message SOAPMessage reply = onMessage(message); // If there is a reply, return it to the sender. if (reply != null) { // Set OK HTTP status, unless there is a fault. boolean hasFault = reply.getSOAPPart().getEnvelope().getBody().hasFault(); response.setStatus(hasFault ? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : HttpServletResponse.SC_OK); // Force generation of the MIME headers if (reply.saveRequired()) { reply.saveChanges(); } // Copy the MIME headers to the HTTP response setHttpHeaders(reply.getMimeHeaders(), response); // Send the completed message OutputStream os = response.getOutputStream(); reply.writeTo(os); os.flush(); } else { // No reply - set the HTTP status to indicate this response.setStatus(HttpServletResponse.SC_NO_CONTENT); } } catch (SOAPException ex) { throw new ServletException("SOAPException: " + ex); } } /** * Method implemented by subclasses to handle a received SOAP message. * @param message the received SOAP message. * @return the reply message, or <code>null</code> if there is * no reply to be sent. */ protected abstract SOAPMessage onMessage(SOAPMessage message) throws SOAPException; /** * Creates a MIMEHeaders object from the HTTP headers * received with a SOAP message. */ private MimeHeaders getMIMEHeaders(HttpServletRequest request) { MimeHeaders mimeHeaders = new MimeHeaders(); Enumeration enum = request.getHeaderNames(); while (enum.hasMoreElements()) { String headerName = (String)enum.nextElement(); String headerValue = request.getHeader(headerName); StringTokenizer st = new StringTokenizer(headerValue, ","); while (st.hasMoreTokens()) { mimeHeaders.addHeader(headerName, st.nextToken().trim()); } } return mimeHeaders; } /** * Converts the MIMEHeaders for a SOAP message to * HTTP headers in the response. */ private void setHttpHeaders(MimeHeaders mimeHeaders, HttpServletResponse response) { Iterator iter = mimeHeaders.getAllHeaders(); while (iter.hasNext()) { MimeHeader mimeHeader = (MimeHeader)iter.next(); String headerName = mimeHeader.getName(); String[] headerValues = mimeHeaders.getHeader(headerName); int count = headerValues.length; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < count; i++) { if (i != 0) { buffer.append(','); } buffer.append(headerValues[i]); } response.setHeader(headerName, buffer.toString()); } } }
package ora.jwsnut.chapter3.bookimageservice;
import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Iterator; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.xml.soap.AttachmentPart; import javax.xml.soap.Detail; import javax.xml.soap.DetailEntry; import javax.xml.soap.MessageFactory; import javax.xml.soap.Name; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPBodyElement; import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPFault; import javax.xml.soap.SOAPMessage; import ora.jwsnut.saaj.SAAJServlet;
/** * A servlet that uses SAAJ attachments to * serve images to a client. */ public class BookImageServlet extends SAAJServlet { // The XML Schema namespace private static final String XMLSCHEMA_URI = "http://www.w3.org/2001/XMLSchema"; // The XML Schema instance namespace private static final String XMLSCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
// Namespace prefix for XML Schema private static final String XMLSCHEMA_PREFIX = "xsd";
// Namespace prefix for XML Schema instance private static final String XMLSCHEMA_INSTANCE_PREFIX = "xsi"; // The namespace prefix used for SOAP encoding private static final String SOAP_ENC_PREFIX = "SOAP-ENC"; // The URI used to qualify elements for this service private static final String SERVICE_URI = "urn:jwsnut.bookimageservice"; // The namespace prefix used in elements for this service private static final String SERVICE_PREFIX = "tns"; // MessageFactory for replies from this service private static MessageFactory messageFactory; // SOAPFactory for message pieces private static SOAPFactory soapFactory; // The name of the element used to request a book name list private static Name BOOK_LIST_NAME; // The name of the element used to reply to a book name list request private static Name BOOK_TITLES_NAME; // The name of the element used to request a book image private static Name BOOK_IMAGE_REQUEST_NAME; // The name of the element used to respond to a book image request private static Name BOOK_IMAGES_NAME; // The name of the attribute used to hold the image encoding private static Name IMAGE_TYPE_ATTRIBUTE; // The name of the href attribute private static Name HREF_ATTRIBUTE; /** * Handles a received SOAP message. */ public SOAPMessage onMessage(SOAPMessage message) throws SOAPException { if (messageFactory == null) { // Create all static data on first call messageFactory = MessageFactory.newInstance(); soapFactory = SOAPFactory.newInstance(); BOOK_LIST_NAME = soapFactory.createName("BookList", SERVICE_PREFIX, SERVICE_URI); BOOK_TITLES_NAME = soapFactory.createName("BookTitles", SERVICE_PREFIX, SERVICE_URI); BOOK_IMAGE_REQUEST_NAME = soapFactory.createName("BookImageRequest", SERVICE_PREFIX, SERVICE_URI); BOOK_IMAGES_NAME = soapFactory.createName("BookImages", SERVICE_PREFIX, SERVICE_URI); IMAGE_TYPE_ATTRIBUTE = soapFactory.createName("imageType", SERVICE_PREFIX, SERVICE_URI); HREF_ATTRIBUTE = soapFactory.createName("href"); } // Create the reply message and define the namespace // and encoding for the elements used in the reply. SOAPMessage reply = messageFactory.createMessage(); SOAPEnvelope replyEnvelope = reply.getSOAPPart().getEnvelope(); replyEnvelope.getHeader().detachNode(); replyEnvelope.addNamespaceDeclaration(SERVICE_PREFIX, SERVICE_URI); replyEnvelope.addNamespaceDeclaration(SOAP_ENC_PREFIX, SOAPConstants.URI_NS_SOAP_ENCODING); replyEnvelope.addNamespaceDeclaration(XMLSCHEMA_PREFIX, XMLSCHEMA_URI); replyEnvelope.addNamespaceDeclaration(XMLSCHEMA_INSTANCE_PREFIX, XMLSCHEMA_INSTANCE_URI); replyEnvelope.setEncodingStyle(SOAPConstants.URI_NS_SOAP_ENCODING); SOAPBody replyBody = reply.getSOAPPart().getEnvelope().getBody(); // There are two requests - one for the list of // book titles, the other for the image for a book. SOAPBody requestBody = message.getSOAPPart().getEnvelope().getBody(); Iterator iter = requestBody.getChildElements(); if (iter.hasNext()) { // The child element contains the request SOAPElement element = (SOAPElement)iter.next(); Name elementName = element.getElementName(); if (elementName.equals(BOOK_LIST_NAME)) { handleBookListRequest(replyBody); } else if (elementName.equals(BOOK_IMAGE_REQUEST_NAME)) { handleBookImageRequest(element, reply); } else { // Unrecognized request - this is a fault. createFault(replyBody, "soap-env:Client.UnknownRequest", "Unrecognized request", SERVICE_URI, elementName.getLocalName()); } } else { // No request - this is a fault createFault(replyBody, "soap-env:Client.MissingRequest", "Missing request", SERVICE_URI, "No request found"); } return reply; } /** * Handles a request for list of book names. */ private void handleBookListRequest(SOAPBody replyBody) throws SOAPException { // Create a BookTitles element containing an entry // for each book title. SOAPBodyElement bodyElement = replyBody.addBodyElement(BOOK_TITLES_NAME); // Add 'xsi:type = "SOAP-ENC:Array"' bodyElement.addAttribute( soapFactory.createName("type", XMLSCHEMA_INSTANCE_PREFIX, XMLSCHEMA_INSTANCE_URI), SOAP_ENC_PREFIX + ":Array"); // Add 'SOAP-ENC:arrayType = "xsd:string[]" bodyElement.addAttribute( soapFactory.createName("arrayType", SOAP_ENC_PREFIX, SOAPConstants.URI_NS_SOAP_ENCODING), XMLSCHEMA_PREFIX + ":string[]"); // Add an array entry for each book String[] titles = BookImageServletData.getBookTitles(); for (int i = 0; i < titles.length; i++) { SOAPElement titleElement = bodyElement.addChildElement("item"); titleElement.addTextNode(titles[i]); } } /** * Handles a request for the images for a given list of book. */ private void handleBookImageRequest(SOAPElement element, SOAPMessage reply) throws SOAPException { // The request element contains an attribute that holds the // type of image requested and a nested string for each title. // The reply body has a BookImages element and a nested item with // a reference to the image which is sent as an attachment SOAPBody replyBody = reply.getSOAPPart().getEnvelope().getBody(); // Determine whether to use JPEG or GIF images String imageType = element.getAttributeValue(IMAGE_TYPE_ATTRIBUTE); boolean gif = imageType.equalsIgnoreCase("image/gif"); // Build the BookImages element containing all of the replies SOAPBodyElement bodyElement = replyBody.addBodyElement(BOOK_IMAGES_NAME); bodyElement.addAttribute( soapFactory.createName("type", XMLSCHEMA_INSTANCE_PREFIX, XMLSCHEMA_INSTANCE_URI), SOAP_ENC_PREFIX + ":Array"); bodyElement.addAttribute( soapFactory.createName("arrayType", SOAP_ENC_PREFIX, SOAPConstants.URI_NS_SOAP_ENCODING), XMLSCHEMA_PREFIX + ":anyType[]"); // Index of the next attachment to use int index = 0; // Handle each nested element. Iterator iter = element.getChildElements(); while (iter.hasNext()) { // Get the next child element from the request message SOAPElement childElement = (SOAPElement)iter.next(); // Get the book title String title = childElement.getValue(); // Get the image data byte[] imageData = BookImageServletData.getBookImage(title, gif); if (imageData != null) { // Got the data - attach it. AttachmentPart attach = reply.createAttachmentPart(); attach.setDataHandler(new DataHandler( new ByteArrayDataSource("Image Data", imageData, gif ? "image/gif" : "image/jpeg"))); attach.setContentId("ID" + index); reply.addAttachmentPart(attach);
// Add an element in the reply pointing to the attachment bodyElement.addChildElement("item").addAttribute(HREF_ATTRIBUTE, "cid:ID" + index); // Increment the index index++; } else { // No data - this is a fault. // Clear the reply and install the fault reply.removeAllAttachments(); bodyElement.detachNode(); createFault(replyBody, "soap-env:Client.Title", "Unknown title", SERVICE_URI, title); return; } } } /** * Creates a fault in the reply body. */ private void createFault(SOAPBody replyBody, String faultCode, String faultString, String faultActor, String detailString) throws SOAPException { SOAPFault fault = replyBody.addFault(); fault.setFaultCode(faultCode); fault.setFaultString(faultString); fault.setFaultActor(faultActor); if (detailString != null) { Name detailName = soapFactory.createName("BookFaultDetail", SERVICE_PREFIX, SERVICE_URI); Detail detail = fault.addDetail(); DetailEntry detailEntry = detail.addDetailEntry(detailName); detailEntry.addTextNode(detailString); } } }
/** * A private DataSource implementation that * allows byte streams of arbitrary types to * be associated with a DataHandler. */ class ByteArrayDataSource implements DataSource {
private String contentType; private byte[] data; private String name; ByteArrayDataSource(String name, byte[] data, String contentType) { this.name = name; this.data = data; this.contentType = contentType; } public String getContentType() { return contentType; } public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(data); } public String getName() { return name; } public OutputStream getOutputStream() throws IOException { throw new IOException("ByteArrayDataSource cannot support getOutputStream()"); } }
package ora.jwsnut.chapter3.bookimageservice;
import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.StringTokenizer;
class BookImageServletData { /** * Map from book name to image data */ private static HashMap bookMap; /** * List of book titles. */ private static String[] bookTitles; /** * Buffer used when reading image data */ private static byte[] buffer; /** * Stream used when reading image data */ private static ByteArrayOutputStream os; /** * Gets an image for a book with a given title. * @param title the book title * @param gif <code>true</code> to return GIF data, * <code>false</code> for JPEG data. */ static byte[] getBookImage(String title, boolean gif) { byte[] data = null; if (bookMap == null) { // Load the data on first call getBookImageData(); } if (bookMap != null) { byte[][] imageData = (byte[][])bookMap.get(title); if (imageData != null) { data = imageData[gif ? 1 : 0]; } } return data; } /** * Gets a list of all of the book names. */ public static String[] getBookTitles() { if (bookTitles == null) { if (bookMap == null) { // Load the data on first call getBookImageData(); }
if (bookMap != null) { bookTitles = new String[bookMap.size()]; Iterator iter = bookMap.keySet().iterator(); int index = 0; while (iter.hasNext()) { bookTitles[index++] = (String)iter.next(); } } else { bookTitles = new String[0]; } } return bookTitles; } /** * Gets the book image data in the form of a HashMap * where the key is the book title and the value is * a two dimensional byte array in which the first * array provides a JPEG image and the second a GIF. */ private static void getBookImageData() { try { bookMap = new HashMap(); InputStream is = BookImageServletData.class.getResourceAsStream("booklist.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); buffer = new byte[1024]; os = new ByteArrayOutputStream(); String line; while ((line = reader.readLine()) != null) { StringTokenizer st = new StringTokenizer(line, "!"); if (st.countTokens() == 3) { String title = st.nextToken(); String jpegImagePath = st.nextToken(); String gifImagePath = st.nextToken(); byte[][] imageData = new byte[2][]; imageData[0] = getImage(jpegImagePath); imageData[1] = getImage(gifImagePath); bookMap.put(title, imageData); } } buffer = null; os.close(); os = null; } catch (Exception ex) { // Just return an empty or partial map ex.printStackTrace(); } } /** * Reads an image file and returns the content. */ private static byte[] getImage(String path) throws IOException { InputStream is = BookImageServletData.class.getResourceAsStream(path); int count; while ((count = is.read(buffer, 0, buffer.length)) > 0) { os.write(buffer, 0, count); } byte[] content = os.toByteArray(); os.reset(); return content; } }
booklist.txt
Java in a Nutshell!images/javanut.jpg!images/javanut.gif Java Foundation Classes in a Nutshell!images/jfcnut.jpg!images/jfcnut.gif J2ME in a Nutshell!images/j2meanut.jpg!images/j2meanut.gif Java Swing!images/jswing.jpg!images/jswing.gif Java Servlet Programming!images/jservlet.jpg!images/jservlet.gif Enterprise JavaBeans!images/ejb.jpg!images/ejb.gif JavaServer Pages!images/jserverpages.jpg!images/jserverpages.gif Java I/O!images/javaio.jpg!images/javaio.gif Java 2D Graphics!images/java2d.jpg!images/java2d.gif Creating Effective JavaHelp!images/creatingjavahelp.jpg!images/creatingjavahelp.gif Java Performance Tuning!images/javapt.jpg!images/javapt.gif Java Internationalization!images/javaint.jpg!images/javaint.gif
客户端代码:
package ora.jwsnut.chapter3.client;
import java.awt.BorderLayout; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.JPanel; import javax.xml.soap.AttachmentPart; import javax.xml.soap.MessageFactory; import javax.xml.soap.MimeHeader; import javax.xml.soap.MimeHeaders; import javax.xml.soap.Name; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPBodyElement; import javax.xml.soap.SOAPConnection; import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPFault; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage;
/** * SAAJ client that receives images from a web service. */ public class BookImageClient { // The XML Schema namespace private static final String XMLSCHEMA_URI = "http://www.w3.org/2001/XMLSchema"; // The XML Schema instance namespace private static final String XMLSCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
// Namespace prefix for XML Schema private static final String XMLSCHEMA_PREFIX = "xsd";
// Namespace prefix for XML Schema instance private static final String XMLSCHEMA_INSTANCE_PREFIX = "xsi"; // The namespace prefix used for SOAP encoding private static final String SOAP_ENC_PREFIX = "SOAP-ENC"; // The URI used to qualify elements for this service private static final String SERVICE_URI = "urn:jwsnut.bookimageservice"; // The namespace prefix used in elements for this service private static final String SERVICE_PREFIX = "tns"; // MessageFactory for replies from this service private static MessageFactory messageFactory; // SOAPFactory for message pieces private static SOAPFactory soapFactory; // SOAPConnection used to call the server private static SOAPConnection conn; // The name of the element used to request a book name list private static Name BOOK_LIST_NAME; // The name of the element used to reply to a book name list request private static Name BOOK_TITLES_NAME; // The name of the element used to request a book image private static Name BOOK_IMAGE_REQUEST_NAME; // The name of the element used to respond to a book image request private static Name BOOK_IMAGES_NAME; // The name of the attribute used to hold the image encoding private static Name IMAGE_TYPE_ATTRIBUTE; // The name of the href attribute private static Name HREF_ATTRIBUTE; // Server address private static String serverAddress; // Debug required flag private static boolean debug; public static void main(String[] args) { // Ignore hostname verification failures HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); if (args.length != 1) { usage(); } serverAddress = args[0]; // Determine whether debug messages are required debug = System.getProperty("DEBUG_MESSAGE") != null;
try { // Create all static data messageFactory = MessageFactory.newInstance(); soapFactory = SOAPFactory.newInstance(); BOOK_LIST_NAME = soapFactory.createName("BookList", SERVICE_PREFIX, SERVICE_URI); BOOK_TITLES_NAME = soapFactory.createName("BookTitles", SERVICE_PREFIX, SERVICE_URI); BOOK_IMAGE_REQUEST_NAME = soapFactory.createName("BookImageRequest", SERVICE_PREFIX, SERVICE_URI); BOOK_IMAGES_NAME = soapFactory.createName("BookImages", SERVICE_PREFIX, SERVICE_URI); IMAGE_TYPE_ATTRIBUTE = soapFactory.createName("imageType", SERVICE_PREFIX, SERVICE_URI); HREF_ATTRIBUTE = soapFactory.createName("href"); // Get a SOAPConnection SOAPConnectionFactory connFactory = SOAPConnectionFactory.newInstance(); conn = connFactory.createConnection(); // Get the book titles from the server String[] titles = getBookTitles(); Arrays.sort(titles);
// Build the user interface showGui(titles); } catch (Exception ex) { System.out.println(ex); } } public static void usage() { System.err.println("Usage: java BookImageClient address"); System.exit(1); } /** * Builds the message used to request the book titles, * sends it and extracts the titles from the reply. */ private static String[] getBookTitles() throws SOAPException, IOException { // Build the message SOAPMessage message = messageFactory.createMessage();
// Remove the message header SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); envelope.getHeader().detachNode();
// Set up the namespace declaration envelope.addNamespaceDeclaration(SERVICE_PREFIX, SERVICE_URI);
// Add the element for the book list request SOAPBody soapBody = envelope.getBody(); soapBody.addBodyElement(BOOK_LIST_NAME);
// Print the message. printMessage(message); SOAPMessage reply = conn.call(message, serverAddress); // Print the reply printMessage(reply); SOAPBody replyBody = reply.getSOAPPart().getEnvelope().getBody(); if (replyBody.hasFault()) { SOAPFault fault = replyBody.getFault(); throw new SOAPException("Fault when getting book titles: " + fault.getFaultString()); } // The body contains a "BookTitles" element with a nested // element for each book title. Iterator iter = replyBody.getChildElements(BOOK_TITLES_NAME); if (iter.hasNext()) { ArrayList list = new ArrayList(); SOAPElement bookTitles = (SOAPElement)iter.next(); iter = bookTitles.getChildElements(); while (iter.hasNext()) { list.add(((SOAPElement)iter.next()).getValue()); } int size = list.size(); String[] titles = new String[size]; list.toArray(titles); return titles; } else { // No BookTitles element was found throw new SOAPException("No BookTitles element in returned message"); } } /** * Gets the images for the books with the supplied titles. */ private static Image[] getImages(Object[] titles, boolean gif) throws SOAPException, IOException { // Build the message SOAPMessage message = messageFactory.createMessage();
// Remove the message header SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); envelope.getHeader().detachNode();
// Set up the namespaces and the encoding style envelope.addNamespaceDeclaration(SERVICE_PREFIX, SERVICE_URI); envelope.addNamespaceDeclaration(SOAP_ENC_PREFIX, SOAPConstants.URI_NS_SOAP_ENCODING); envelope.addNamespaceDeclaration(XMLSCHEMA_PREFIX, XMLSCHEMA_URI); envelope.addNamespaceDeclaration(XMLSCHEMA_INSTANCE_PREFIX, XMLSCHEMA_INSTANCE_URI); envelope.setEncodingStyle(SOAPConstants.URI_NS_SOAP_ENCODING);
// Add the element for the book image request SOAPBody soapBody = envelope.getBody(); SOAPBodyElement bodyElement = soapBody.addBodyElement(BOOK_IMAGE_REQUEST_NAME); // Add 'xsi:type = "SOAP-ENC:Array"' bodyElement.addAttribute( soapFactory.createName("type", XMLSCHEMA_INSTANCE_PREFIX, XMLSCHEMA_INSTANCE_URI), SOAP_ENC_PREFIX + ":Array"); // Add 'SOAP-ENC:arrayType = "xsd:string[]" bodyElement.addAttribute( soapFactory.createName("arrayType", SOAP_ENC_PREFIX, SOAPConstants.URI_NS_SOAP_ENCODING), XMLSCHEMA_PREFIX + ":string[]"); // Add the image type attribute bodyElement.addAttribute(IMAGE_TYPE_ATTRIBUTE, gif ? "image/gif" : "image/jpeg");
// Add an array entry for each book for (int i = 0; i < titles.length; i++) { SOAPElement titleElement = bodyElement.addChildElement("item"); titleElement.addTextNode(titles[i].toString()); }
// Print the message. printMessage(message); SOAPMessage reply = conn.call(message, serverAddress); // Print the reply printMessage(reply); SOAPBody replyBody = reply.getSOAPPart().getEnvelope().getBody(); if (replyBody.hasFault()) { SOAPFault fault = replyBody.getFault(); throw new SOAPException("Fault when getting book images: " + fault.getFaultString() + ", actor is [" + fault.getFaultActor() + "]"); } // The body contains a "BookImages" element with a nested // element for each book title. Iterator iter = replyBody.getChildElements(BOOK_IMAGES_NAME); if (iter.hasNext()) { ArrayList list = new ArrayList(); MimeHeaders headers = new MimeHeaders(); SOAPElement bookImages = (SOAPElement)iter.next(); iter = bookImages.getChildElements(); while (iter.hasNext()) { SOAPElement element = (SOAPElement)iter.next(); String imageRef = element.getAttributeValue(HREF_ATTRIBUTE); if (imageRef != null) { // Get the attachment using the Content-Id, having // first removed the "cid:" prefix imageRef = imageRef.substring(4); headers.setHeader("Content-Id", imageRef); Iterator attachIter = reply.getAttachments(headers); if (attachIter.hasNext()) { AttachmentPart attach = (AttachmentPart)attachIter.next(); Object content = attach.getContent(); if (content instanceof Image) { list.add(content); } } } } int size = list.size(); Image[] images = new Image[size]; list.toArray(images); return images; } else { // No BookTitles element was found throw new SOAPException("No BookImages element in returned message"); } } /* -- User interface -- */ private static void showGui(String[] titles) throws SOAPException { JFrame frame = new JFrame("SAAJ Example"); JPanel mainPanel = new JPanel(new BorderLayout()); // Add an unknown title to the book list String[] fullTitles = new String[titles.length + 1]; System.arraycopy(titles, 0, fullTitles, 0, titles.length); fullTitles[titles.length] = "No Such Book"; final JList titleList = new JList(fullTitles); final JPanel imagePanel = new JPanel(); mainPanel.add(new JScrollPane(imagePanel), BorderLayout.CENTER); JPanel controls = new JPanel(); controls.setLayout(new BoxLayout(controls, BoxLayout.X_AXIS)); mainPanel.add(controls, BorderLayout.SOUTH); final JCheckBox isGif = new JCheckBox("Use GIF images"); JButton fetchButton = new JButton("Fetch"); controls.add(isGif); controls.add(Box.createHorizontalGlue()); controls.add(fetchButton); frame.getRootPane().setDefaultButton(fetchButton); frame.getContentPane().add(new JScrollPane(titleList), BorderLayout.WEST); frame.getContentPane().add(mainPanel, BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { public void windowClosed(WindowEvent evt) { System.exit(0); } }); fetchButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { Object[] selections = titleList.getSelectedValues(); imagePanel.removeAll(); imagePanel.validate(); if (selections.length > 0) { try { Image[] images = getImages(selections, isGif.isSelected()); for (int i = 0; i < images.length; i++) { imagePanel.add(new JLabel(new ImageIcon(images[i]))); } imagePanel.revalidate(); imagePanel.repaint(); } catch (Exception ex) { System.out.println(ex); } } } }); frame.setSize(640, 300); frame.setVisible(true); } /* -- Debug methods -- */ private static void printMessage(SOAPMessage message) throws IOException, SOAPException { if (debug && message != null) { // Get the MIME headers and print them System.out.println("Headers:"); if (message.saveRequired()) { message.saveChanges(); } MimeHeaders headers = message.getMimeHeaders(); printHeaders(headers); // Print the message itself System.out.println("/nMessage:"); message.writeTo(System.out); System.out.println(); } } private static void printHeaders(MimeHeaders headers) { if (debug) { printHeaders(headers.getAllHeaders()); } } private static void printHeaders(Iterator iter) { if (debug) { while (iter.hasNext()) { MimeHeader header = (MimeHeader)iter.next(); System.out.println("/t" + header.getName() + ": " + header.getValue()); } } } }
ant文件:
<!ENTITY buildsetup SYSTEM "../../common/buildsetup.xml"> <!ENTITY deploy SYSTEM "../../common/deploy.xml"> 这里声明的文件同上一篇的相同。并且在使用时改变文件路径。
build.xml
<!DOCTYPE project [ <!ENTITY buildsetup SYSTEM "../../common/buildsetup.xml"> <!ENTITY deploy SYSTEM "../../common/deploy.xml"> <!ENTITY saajcommon SYSTEM "../common/saajcommon.xml"> ]>
<project name="BookImageService" basedir="." default="web-package"> <!-- Import common elements --> &buildsetup; &saajcommon; &deploy;
<!-- Check that this example is appropriate for the current platform --> <target name="platform-check"> <!-- Nothing to check --> </target> <!-- Targets that are private to this project --> <!-- Executes the client test with basic authentication --> <target name="run-basicauth-client" if="client.present" depends="init"> <java classname="${CLIENT_CLASS_NAME}" fork="yes"> <sysproperty key="http.proxyHost" value="${HTTP_PROXY_SERVER}"/> <sysproperty key="http.proxyPort" value="${HTTP_PROXY_PORT}"/> <sysproperty key="https.proxyHost" value="${HTTPS_PROXY_SERVER}"/> <sysproperty key="https.proxyPort" value="${HTTPS_PROXY_PORT}"/> <arg line="${CLIENT_BASIC_AUTH_ARGS}"/> <classpath refid="run.path"/> </java> </target>
<!-- Executes the client test with https and server authentication --> <target name="run-httpsserver-client" if="client.present" depends="init"> <java classname="${CLIENT_CLASS_NAME}" fork="yes"> <sysproperty key="http.proxyHost" value="${HTTP_PROXY_SERVER}"/> <sysproperty key="http.proxyPort" value="${HTTP_PROXY_PORT}"/> <sysproperty key="https.proxyHost" value="${HTTPS_PROXY_SERVER}"/> <sysproperty key="https.proxyPort" value="${HTTPS_PROXY_PORT}"/> <sysproperty key="javax.net.ssl.trustStore" value="${EXAMPLES_ROOT}/client.keystore"/> <sysproperty key="javax.net.ssl.trustStorePassword" value="changeit"/> <arg line="${CLIENT_HTTPS_SERVER_AUTH_ARGS}"/> <classpath refid="run.path"/> </java> </target>
<!-- Executes the client test with https and server authentication with debug --> <target name="run-httpsserver-client-debug" if="client.present" depends="init"> <java classname="${CLIENT_CLASS_NAME}" fork="yes"> <sysproperty key="http.proxyHost" value="${HTTP_PROXY_SERVER}"/> <sysproperty key="http.proxyPort" value="${HTTP_PROXY_PORT}"/> <sysproperty key="https.proxyHost" value="${HTTPS_PROXY_SERVER}"/> <sysproperty key="https.proxyPort" value="${HTTPS_PROXY_PORT}"/> <sysproperty key="javax.net.ssl.trustStore" value="${EXAMPLES_ROOT}/client.keystore"/> <sysproperty key="javax.net.ssl.trustStorePassword" value="changeit"/> <sysproperty key="javax.net.debug" value="all"/> <arg line="${CLIENT_HTTPS_SERVER_AUTH_ARGS}"/> <classpath refid="run.path"/> </java> </target>
</project>
saajcommon.xml
<!-- Common build targets for SAAJ examples -->
<!-- Source directories --> <property name="SERVER_SRC_DIR" value="${basedir}/server"/> <property name="CLIENT_SRC_DIR" value="${basedir}/client"/>
<!-- Output directories --> <property name="OUTPUT_DIR" value="${basedir}/output"/> <property name="SERVER_OUTPUT_DIR" value="${OUTPUT_DIR}/server"/> <property name="CLIENT_OUTPUT_DIR" value="${OUTPUT_DIR}/client"/>
<!-- Directory containing the SAAJ servlet --> <property name="SAAJ_SERVLET_DIR" value="${EXAMPLES_ROOT}/chapter3/servlet"/>
<!-- Sets properties to indicate whether there are client and/or server parts --> <target name="check-dirs" depends="check" unless="check.done"> <available file="${SERVER_SRC_DIR}" property="server.present"/> <available file="${CLIENT_SRC_DIR}" property="client.present"/> <property name="check.done" value="true"/> </target>
<!-- Makes the client output directory, but only if there is client code --> <target name="client-dir" if="client.present" depends="check-dirs"> <mkdir dir="${CLIENT_OUTPUT_DIR}"/> </target>
<!-- Makes the server output directory, but only if there is server code --> <target name="server-dir" if="server.present" depends="check-dirs"> <mkdir dir="${SERVER_OUTPUT_DIR}"/> </target>
<target name="init" depends="prepare, client-dir, server-dir">
<!-- Compilation class path --> <path id="compile.path"> <!-- Required for access to SAAJ classes --> <path refid="basic.classpath"/> <pathelement location="${SAAJ_SERVLET_DIR}"/> </path>
<!-- Client execution class path --> <path id="run.path"> <!-- Required for access to SAAJ classes --> <path refid="basic.classpath"/>
<!-- Access to SAAJ client code --> <pathelement location="${CLIENT_OUTPUT_DIR}"/> </path> </target>
<!-- Target that ensures that the SAAJ servlet is up to date --> <target name="saaj-servlet" if="server.present" depends="init"> <ant dir="${SAAJ_SERVLET_DIR}"/> </target>
<!-- Target that cleans the SAAJ servlet directory --> <target name="saaj-clean" if="server.present" depends="check"> <ant dir="${SAAJ_SERVLET_DIR}" target="clean"/> </target>
<!-- Target that cleans the SAAJ servlet directory of all files --> <target name="saaj-pub-clean" if="server.present" depends="saaj-clean"> <ant dir="${SAAJ_SERVLET_DIR}" target="pub-clean"/> </target>
<!-- Compilation of the server part --> <target name="compile-server" if="server.present" depends="saaj-servlet"> <javac srcdir="${SERVER_SRC_DIR}" destdir="${SERVER_OUTPUT_DIR}" debug="true"> <classpath refid="compile.path"/> </javac>
<!-- Include resource files from the server source tree --> <copy todir="${SERVER_OUTPUT_DIR}"> <fileset dir="${SERVER_SRC_DIR}"> <exclude name="**/*.java"/> <exclude name="web.xml"/> </fileset> </copy> </target>
<!-- Compilation of the client part --> <target name="compile-client" if="client.present" depends="init"> <javac srcdir="${CLIENT_SRC_DIR}" destdir="${CLIENT_OUTPUT_DIR}" debug="true"> <classpath refid="compile.path"/> </javac> </target>
<!-- Target that generates and compiles everything --> <target name="compile" depends="compile-server, compile-client"/>
<!-- Target that builds the WAR file for web deployment --> <target name="web-package" if="server.present" depends="compile-server"> <war warfile="${WEB_ARCHIVE_NAME}" webxml="${SERVER_SRC_DIR}/web.xml">
<!-- Include the SAAJServlet class --> <classes dir="${SAAJ_SERVLET_DIR}" includes="**/*.class"/> <!-- Include the server files --> <classes dir="${SERVER_OUTPUT_DIR}"/> </war> </target>
<!-- Dummy target, not used by SAAJ examples --> <target name="portable-web-package"/>
<!-- Executes the client test --> <target name="run-client" if="client.present" depends="init"> <java classname="${CLIENT_CLASS_NAME}" fork="yes"> <arg line="${CLIENT_ARGS}"/> <classpath refid="run.path"/> </java> </target>
<!-- Executes the client test and requests debug output --> <target name="run-client-debug" if="client.present" depends="init"> <java classname="${CLIENT_CLASS_NAME}" fork="yes"> <arg line="${CLIENT_ARGS}"/> <classpath refid="run.path"/> <sysproperty key="DEBUG_MESSAGE" value="true"/> </java> </target>
<!-- Cleans up by removing all intermediate files and outputs --> <target name="clean" depends="clean-common, saaj-clean, check"> <delete dir="${OUTPUT_DIR}"/> <delete dir="${TEMP_DEPLOY_DIR}"/> <delete file="${WEB_ARCHIVE_NAME}"/> </target>