Home TOC |
![]() ![]() ![]() |
Tutorial
This section will walk you through the basics of sending a SOAP message using the JAXM API. At the end of this chapter, you will know how to do the following:
- Get a connection
- Create a message
- Add content to a message
- Send the message
- Retrieve the content in a message and an attachment
First, we'll walk through the steps in sending a request-response message for a client that does not use a messaging provider. Then we'll do a walkthrough of a client that uses a messaging provider sending a one-way message. Both types of client may add attachments to a message, so adding attachments is covered last as a separate topic.
Client without a Messaging Provider
An application that does not use a messaging provider is limited to operating in a client role and can send only request-response messages. Though limited, it can make use of Web services that are implemented to do request-response messaging.
Getting a SOAPConnection Object
The first thing any JAXM client needs to do is get a connection, either a
SOAPConnection
object or aProviderConnection
object. The overview section discusses these two types of connections and how they are used.A client that does not use a messaging provider has only one choice for creating a connection, which is to create a
SOAPConnection
object. This kind of connection is a point-to-point connection, meaning that it goes directly from the sender to the URL that the sender specifies.The first step is to obtain a
SOAPConnectionFactory
object that you can use to create your connection. The JAXM API makes this easy by providing theSOAPConnectionFactory
class with a default implementation. You can get an instance of this implementation with the following line of code.SOAPConnectionFactory scFactory = SOAPConnectionFactory.newInstance();Notice that because
newInstance
is a static method, you will always use the class nameSOAPConnectionFactory
when you invoke itsnewInstance
method.Now you can use
scFactory
to create aSOAPConnection
object.SOAPConnection con = scFactory.createConnection();You will use
con
later to send the message that is created in the next part.Creating a Message
The next step is to create a message, which you do using a
MessageFactory
object. If you are a standalone client, you can use the default implementation of theMessageFactory
class that the JAXM API provides. The following code fragment illustrates getting an instance of this default message factory and then using it to create a message.MessageFactory factory = MessageFactory.newInstance(); SOAPMessage message = factory.createMessage();As is true of the
newInstance
method forSOAPConnectionFactory
, thenewInstance
method forMessageFactory
is static, so you invoke it by callingMessageFactory.newInstance
. Note that it is possible to write your own implementation of a message factory and plug it in via system properties, but the default message factory will almost always be the one that is used.The other way to get a
MessageFactory
object is to retrieve it from a naming service where it has been registered. This way is available only to applications that use a messaging provider, and it will be covered later.Parts of a Message
A
SOAPMessage
object is required to have certain elements, and the JAXM API simplifies things for you by returning a newSOAPMessage
object that already contains these elements. Somessage
, which was created in the preceding line of code, has the following:I. A
SOAPPart
object that containsA. A
SOAPEnvelope
object that containsThe
SOAPHeader
object, though optional, is included for convenience because most messages will use it. TheSOAPBody
object can hold the content of the message and can also contain fault messages that contain status information or details about a problem with the message.Accessing Elements of a Message
The next step in creating a message is to access its parts so that content can be added. The
SOAPMessage
objectmessage
, created in the previous code fragment, is where to start. It contains aSOAPPart
object, so you usemessage
to retrieve it.SOAPPart soapPart = message.getSOAPPart();Next you can use
soapPart
to retrieve theSOAPEnvelope
object that it contains.SOAPEnvelope envelope = soapPart.getEnvelope();You can now use
envelope
to retrieve its emptySOAPHeader
andSOAPBody
objects.SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody();Our example of a standalone client does not use a SOAP header, so you will need to delete it. Because all
SOAPElement
objects, includingSOAPHeader
objects, are derived from theNode
interface, you use the methodNode.detachNode
to deleteheader
.header.detachNode();Adding Content to the Body
To add content to the body, you need to create a
SOAPBodyElement
object to hold the content. When you create any new element, you also need to create an associatedName
object to identify it.Name
objects are created usingSOAPEnvelope
methods, so you can useenvelope
from the previous code fragment to create theName
object for your new element.
Name
objects associated withSOAPBody
andSOAPHeader
objects must be fully qualified; that is, they must be created with a local name, a prefix for the namespace being used, and a URI for the namespace. Specifying a namespace for an element makes clear which one is meant if there is more than one element with the same local name.The code fragment that follows retrieves the
SOAPBody
objectbody
fromenvelope
, creates aName
object for the element to be added, and adds a newSOAPBodyElement
object tobody
.SOAPBody body = envelope.getBody(); Name bodyName = envelope.createName("GetLastTradePrice", "m", "http://wombat.ztrade.com"); SOAPBodyElement gltp = body.addBodyElement(bodyName);At this point,
body
contains aSOAPBodyElement
object identified by theName
objectbodyName
, but there is still no content ingltp
. Assuming that you want to get a quote for the stock of Sun Microsystems, Inc., you need to create a child element for the symbol using the methodaddChildElement
. Then you need to give it the stock symbol using the methodaddTextNode
. TheName
object for the newSOAPElement
objectsymbol
is initialized with only a local name, which is allowed for child elements.Name name = envelope.createName("symbol"); SOAPElement symbol = gltp.addChildElement(name); symbol.addTextNode("SUNW");You might recall that the headers and content in a
SOAPPart
object must be in XML format. The JAXM API takes care of this for you, building the appropriate XML constructs automatically when you call methods such asaddBodyElement
,addChildElement
, andaddTextNode
. Note that you can call the methodaddTextNode
only on an element such asbodyElement
or any child elements that are added to it. You cannot calladdTextNode
on aSOAPHeader
orSOAPBody
object.The content that you have just added to your
SOAPBody
object will look like the following when it is sent over the wire:<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" <SOAP-ENV:Body> <m:GetLastTradePrice xmlns:m= "http://wombat.ztrade.com"> <symbol>SUNW</symbol> </m:GetLastTradePrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope>Let's examine this XML excerpt line by line to see how it relates to your JAXM code. Note that an XML parser does not care about indentations, but they are generally used to indicate element levels and thereby make it easier for a human reader to understand.
SOAPPart soapPart = message.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope();<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" . . . . . . (intervening elements omitted) </SOAP-ENV:Envelope>The outermost element in this XML example is the SOAP envelope element, indicated by
SOAP-ENV:Envelope
.Envelope
is the name of the element, andSOAP-ENV
is the namespace prefix. The interfaceSOAPEnvelope
represents a SOAP envelope.The first line signals the beginning of the SOAP envelope element, and the last line signals the end of it; everything in between is part of the SOAP envelope. The second line has an attribute for the SOAP envelope element.
xmlns
stands for "XML namespace," and its value is the URI of the namespace associated withEnvelope
. This attribute is automatically included for you.SOAPBody body = envelope.getBody();<SOAP-ENV:Body> . . . . . . </SOAP-ENV:Body>These two lines mark the beginning and end of the SOAP body, represented in JAXM by a
SOAPBody
object.Name bodyName = envelope.createName("GetLastTradePrice", "m", "http://wombat.ztrade.com"); SOAPBodyElement gltp = body.addBodyElement(bodyName);<m:GetLastTradePrice xmlns:m= "http://wombat.ztrade.com"> . . . . </m:GetLastTradePrice>These lines are what the
SOAPBodyElement
gltp
in your code represents. "GetLastTradePrice" is its local name, "m" is its namespace prefix, and "http://wombat.ztrade.com" is its namespace URI.Name name = envelope.createName("symbol"); SOAPElement symbol = gltp.addChildElement(name); symbol.addTextNode("SUNW")
;<symbol>SUNW</symbol>The
String
"SUNW"
is the message content that your recipient, the stock quote service, receives.Sending a Message
A standalone client uses a
SOAPConnection
object and must therefore use theSOAPConnection
methodcall
to send a message. This method takes two arguments, the message being sent and the destination to which the message should go. This message is going to the stock quote service indicated by theURLEndpoint
objectendpoint
.URLEndpoint endpoint = new URLEndpoint( "http://wombat.ztrade.com/quotes"); SOAPMessage response = con.call(message, endpoint);Your message sent the stock symbol SUNW; the
SOAPMessage
objectresponse
should contain the last stock price for Sun Microsystems, which you will retrieve in the next section.A connection uses a fair amount of resources, so it is a good idea to close a connection as soon as you are through using it.
con.close();Getting the Content of a Message
The initial steps for retrieving a message's content are the same as those for giving content to a message: You first access the
SOAPBody
object, using the message to get the envelope and the envelope to get the body. Then you access itsSOAPBodyElement
object because that is the element to which content was added in the example. (In a later section you will see how to add content directly to theSOAPBody
object, in which case you would not need to access theSOAPBodyElement
object for adding content or for retrieving it.) To get the content, which was added with the methodNode.addTextNode
, you call the methodNode.getValue
. Note thatgetValue
returns the value of the immediate child of the element that calls the method. Therefore, in the following code fragment,getValue
is called onbodyElement
, the element on which the methodaddTextNode
was called.In order to access
bodyElement
, you need to call the methodgetChildElement
onbody
. PassingbodyName
togetChildElement
returns ajava.util.Iterator
object that contains all of the child elements identified by theName
objectbodyName
. You already know that there is only one, so just calling the methodnext
on it will return theSOAPBodyElement
you want. Note that the methodIterator.next
returns a JavaObject
, so it is necessary to cast theObject
it returns to aSOAPBodyElement
object before assigning it to the variablebodyElement
.SOAPPart sp = response.getSOAPPart(); SOAPEnvelop env = sp.getEnvelope(); SOAPBody sb = sp.getBody(); java.util.Iterator it = sb.getChildElements(bodyName); SOAPBodyElement bodyElement = (SOAPBodyElement)it.next(); String lastPrice = bodyElement.getValue(); System.out.print("
The last price for SUNW is");
System.out.println(lastPrice);If there were more than one element with the name
bodyName
, you would have had to use awhile
loop using the methodIterator.hasNext
to make sure that you got all of them.while (it.hasNext()) { SOAPBodyElement bodyElement = (SOAPBodyElement)it.next(); String lastPrice = bodyElement.getValue(); System.out.print("
The last price for SUNW is");
System.out.println(lastPrice); }At this point, you have seen how to send a request-response message as a standalone client. You have also seen how to get the content from the response. The next part shows you how to send a message using a messaging provider.
Client with a Messaging Provider
Using a messaging provider gives you more flexibility than a standalone client has because it can take advantage of the additional functionality that a messaging provider can offer.
Getting a ProviderConnection Object
Whereas a
SOAPConnection
object is a point-to-point connection directly to a particular URL, aProviderConnection
object is a connection to a messaging provider. With this kind of connection, all messages that you send or receive go through the messaging provider.As with getting a
SOAPConnection
object, the first step is to get a connection factory, but in this case, it is aProviderConnectionFactory
object. You can obtain aProviderConnectionFactory
object by retrieving it from a naming service. This is possible when your application is using a messaging provider and is deployed in a servlet or J2EE container. With aProviderConnectionFactory
object, you can create a connection to a particular messaging provider and thus be able to use the capabilities of a profile that the messaging provider supports.To get a
ProviderConnectionFactory
object, you first supply the logical name of your messaging provider to the container at deployment time. This is the name associated with your messaging provider that has been registered with a naming service based on the Java Naming and Directory Interface("JNDI"). You can then do a lookup using this name to obtain a
ProviderConnectionFactory
object that will create connections to your messaging provider. For example, if the name registered for your messaging provider is "ProviderABC", you can do a lookup on "ProviderABC" to get aProviderConnectionFactory
object and use it to create a connection to your messaging provider. This is what is done in the following code fragment. The first two lines use methods from the JNDI API to retrieve theProviderConnectionFactory
object, and the last line uses a method from the JAXM API to create the connection to the messaging provider. Note that because the JNDI methodlookup
returns a JavaObject
, you must convert it to aProviderConnectionFactory
object before assigning it to the variablepcFactory
.Context ctx = new InitialContext(); ProviderConnectionFactory pcFactory = (ProviderConnectionFactory)ctx.lookup("ProviderABC"); ProviderConnection pcCon = pcFactory.createConnection();You will use
pcCon
, which represents a connection to your messaging provider, to get information about your messaging provider and to send the message you will create in the next section.Creating a Message
You create all JAXM messages by getting a
MessageFactory
object and using it to create theSOAPMessage
object. For the standalone client example, you simply used the defaultMessageFactory
object obtained via the methodMessageFactory.newInstance
. However, when you are using a messaging provider, you obtain theMessageFactory
object in a different way.Getting a MessageFactory
If you are using a messaging provider, you create a
MessageFactory
object by using the methodProviderConnection.createMessageFactory
. In addition, you pass it aString
indicating the profile you want to use. To find out which profiles your messaging provider supports, you need to get aProviderMetaData
object with information about your provider. This is done by calling the methodgetMetaData
on the connection to your provider. Then you need to call the methodgetSupportedProfiles
to get an array of the profiles your messaging provider supports. Supposing that you want to use the ebXML profile, you need to see if any of the profiles in the array matches "ebxml". If there is a match, that profile is assigned to the variableprofile
, which can then be passed to the methodcreateMessageFactory
.ProviderMetaData metaData = pcCon.getMetaData(); String[] supportedProfiles = metaData.getSupportedProfiles(); String profile = null; for (int i=0; i < supportedProfiles.length; i++) { if (supportedProfiles[i].equals("ebxml")) { profile = supportedProfiles[i]; break; } } MessageFactory factory = pcCon.createMessageFactory(profile);You can now use
factory
to create aSOAPMessage
object that conforms to the ebXML profile. This example uses the minimal ebXML profile used in the JAXM RI. Note that the following line of code uses the classEbXMLMEssageImpl
, which is defined in the JAXM RI and is not part of the JAXM API.EbXMLMessageImpl message = (EbXMLMessageImpl)factory. createMessage();For this profile, you need to indicate the
Endpoint
objects for the sender and the receiver. This information will appear in the message's header, and the messaging provider will use it to determine where to send the message. The following lines of code use the methodssetSender
andsetReceiver
, which are provided by the ebXML profile implemented in the JAXM RI. These methods not only create aSOAPHeader
object but also give it content. You can use these methods because yourSOAPMessage
object is anEbXMLMessageImpl
object, giving you access to the methods defined inEbXMLMessageImpl
.message.setSender(new Party("http://grand.products.com")); message.setReceiver(new Party("http://whiz.gizmos.com"));If you are not using a profile or you want to set content for a header not covered by your profile's implementation, you need to follow the steps shown in the next section.
Adding Content to the Header
To add content to the header, you need to create a
SOAPHeaderElement
object. As with all new elements, it must have an associatedName
object, which you create using the message'sSOAPEnvelope
object.The following code fragment retrieves the
SOAPHeader
object fromenvelope
and adds a newSOAPHeaderElement
object to it.SOAPHeader header = envelope.getHeader(); Name headerName = envelope.createName("Purchase Order", "PO", "http://www.sonata.com/order"); SOAPHeaderElement headerElement = header.addHeaderElement(headerName);At this point,
header
contains theSOAPHeaderElement
objectheaderElement
identified by theName
objectheaderName
. Note that theaddHeaderElement
method both createsheaderElement
and adds it toheader
.Now that you have identified
headerElement
withheaderName
and added it toheader
, the next step is to add content toheaderElement
, which the next line of code does with the methodaddTextNode
.headerElement.addTextNode("order");Now you have the
SOAPHeader
objectheader
that contains aSOAPHeaderElement
object whose content is "order".Adding Content to the SOAP Body
The process for adding content to the
SOAPBody
object is the same for clients using a messaging provider as it is for standalone clients. This is also the same as the process for adding content to theSOAPHeader
object. You access theSOAPBody
object, add aSOAPBodyElement
object to it, and add text to theSOAPBodyElement
object. It is possible to add additionalSOAPBodyElement
objects, and it is possible to add subelements to theSOAPBodyElement
objects with the methodaddChildElement
. For each element or child element, you add content with the methodaddTextNode
.The section on the standalone client demonstrated adding one
SOAPBodyElement
object, adding a child element, and giving it some text. The following example shows adding more than oneSOAPBodyElement
and adding text to each of them.The code first creates the
SOAPBodyElement
objectpurchaseLineItems
, which has a fully-qualified namespace associated with it. That is, theName
object for it has a local name, a namespace prefix, and a namespace URI. As you saw earlier, aSOAPBodyElement
object is required to have a fully-qualified namespace, but child elements added to it may haveName
objects with only the local name.SOAPBody body = envelope.getBody(); Name bodyName = envelope.createName("PurchaseLineItems", "PO", "http://sonata.fruitsgalore.com"); SOAPBodyElement purchaseLineItems = body.addBodyElement(bodyName); Name childName = envelope.createName("Order"); SOAPElement order = purchaseLineItems.addChildElement(childName); childName = envelope.createName("Product"); SOAPElement product = order.addChildElement(childName); product.addTextNode("Apple"); childName = envelope.createName("Price"); SOAPElement price = order.addChildElement(childName); price.addTextNode("1.56"); childName = envelope.createName("Order"); SOAPElement order2 = purchaseLineItems.addChildElement(childName); childName = envelope.createName("Product"); SOAPElement product2 = order2.addChildElement(childName); product2.addTextNode("Peach"); childName = envelope.createName("Price"); SOAPElement price2 = order2.addChildElement(childName); price2.addTextNode("1.48");The JAXM code in the preceding example produces the following XML in the SOAP body:
<PO:PurchaseLineItems xmlns:PO="http://www.sonata.fruitsgalore/order"> <Order> <Product>Apple</Product> <Price>1.56</Price> </Order> <Order> <Product>Peach</Product> <Price>1.48</Price> </Order> </PO:PurchaseLineItems>Adding Content to the SOAPPart Object
If the content you want to send is in a file, JAXM provides an easy way to add it directly to the
SOAPPart
object. This means that you do not access theSOAPBody
object and build the XML content yourself, as you did in the previous section.To add a file directly to the
SOAPPart
object, you use ajavax.xml.transform.Source
object from JAXP (the JavaAPI for XML Processing). There are three types of
Source
objects:SAXSource
,DOMSource
, andStreamSource
. AStreamSource
object holds content as an XML document.SAXSource
andDOMSource
objects hold content along with the instructions for transforming the content into an XML document.The following code fragment uses JAXP API to build a
DOMSource
object that is passed to theSOAPPart.setContent
method. The first two lines of code get aDocumentBuilderFactory
object and use it to create theDocumentBuilder
objectbuilder
. Thenbuilder
parses the content file to produce aDocument
object, which is used to initialize a newDOMSource
object.DocumentBuilderFactory dbFactory = DocumentBuilderFactory. newInstance(); DocumentBuilder builder = dbFactory.newDocumentBuilder(); Document doc = builder.parse("file:///music/order/soap.xml"); DOMSource domSource = new DOMSource(doc);The following two lines of code access the
SOAPPart
object and set the newDOMSource
object as its content. The methodSOAPPart.setContent
not only sets content for theSOAPBody
object but also sets the appropriate header for theSOAPHeader
object.SOAPPart soapPart = envelope.getSOAPPart(); soapPart.setContent(domSource);You will see other ways to add content to a message in the section on
AttachmentPart
objects. One big difference to keep in mind is that aSOAPPart
object must contain only XML data, whereas anAttachmentPart
object may contain any type of content.Sending the Message
When the connection is a
ProviderConnection
object, messages have to be sent using the methodProviderConnection.send
. This method sends the message passed to it and returns immediately. Unlike theSOAPConnection
methodcall
, it does not have to block until it receives a response, which leaves the application free to do other things.The
send
method takes only one argument, the message to be sent. It does not need to be given the destination because the messaging provider can use information in the header to figure out where the message needs to go.pcCon.send(message); pcCon.close();Adding Attachments
Adding
AttachmentPart
objects to a message is the same for all clients, whether they use a messaging provider or not. As noted in earlier sections, you can put any type of content, including XML, in anAttachmentPart
object. And because the SOAP part can contain only XML content, you must use anAttachmentPart
object for any content that is not in XML format.Creating an AttachmentPart Object and Adding Content
The
SOAPMessage
object creates anAttachmentPart
object, and the message also has to add the attachment to itself after content has been added. TheSOAPMessage
class has three methods for creating anAttachmentPart
object.The first method creates an attachment with no content. In this case, an
AttachmentPart
method is used later to add content to the attachment.AttachmentPart attachment = message.createAttachmentPart();You add content to
attachment
with theAttachmentPart
methodsetContent
. This method takes two parameters, a JavaObject
for the content, and aString
object that gives the content type. Content in theSOAPBody
part of a message automatically has a Content-Type header with the value "text/xml" because the content has to be an XML document. In contrast, the type of content in anAttachmentPart
object has to be specified because it can be any type.Each
AttachmentPart
object has one or more headers associated with it. When you specify a type to the methodsetContent
, that type is used for the header Content-Type. Content-Type is the only header that is required. You may set other optional headers, such as Content-Id and Content-Location. For convenience, JAXM providesget
andset
methods for the headers Content-Type, Content-Id, and Content-Location. These headers can be helpful in accessing a particular attachment when a message has multiple attachments. For example, to access the attachments that have particular headers, you call theSOAPMessage
methodgetAttachments
and pass it the header or headers you are interested in.The following code fragment shows one of the ways to use the method
setContent
. The JavaObject
being added is aString
, which contains plain text, so the second argument has to be "text/plain". The code also sets a content identifier, which can be used to identify thisAttachmentPart
object. After you have added content toattachment
, you need to addattachment
to theSOAPMessage
object, which is done in the last line.String stringContent = "Update address for Sunny Skies " + "Inc., to 10 Upbeat Street, Pleasant Grove, CA 95439"; attachment.setContent(stringContent, "text/plain"); attachment.setContentId("update_address"); message.addAttachmentPart(attachment);The variable
attachment
now represents anAttachmentPart
object that contains theString
stringContent
and has a header that contains theString
"text/plain". It also has a Content-Id header with "update_address" as its value. And nowattachment
is part ofmessage
.Let's say you also want to attach a jpeg image showing how beautiful the new location is. In this case, the second argument passed to
setContent
must be "image/jpeg" to match the content being added. The code for adding an image might look like the following. For the first attachment, theObject
passed to the methodsetContent
was aString
. In this case, it is a stream.AttachmentPart attachment2 = message.createAttachmentPart(); byte[] jpegData = . . .; ByteArrayInputStream stream = new ByteArrayInputStream( jpegData); attachment2.setContent(stream, "image/jpeg"); message.addAttachmentPart(attachment);The other two
SOAPMessage.createAttachment
methods create anAttachmentPart
object complete with content. One is very similar to theAttachmentPart.setContent
method in that it takes the same parameters and does essentially the same thing. It takes a JavaObject
containing the content and aString
giving the content type. As withAttachmentPart.setContent
, theObject
may be aString
, a stream, ajavax.xml.transform.Source
, or ajavax.activation.DataHandler
object. You have already seen an example of using aSource
object as content. The next example will show how to use aDataHandler
object for content.The other method for creating an
AttachmentPart
object with content takes aDataHandler
object, which is part of the JavaBeansActivation Framework (JAF). Using a
DataHandler
object is fairly straightforward. First you create ajava.net.URL
object for the file you want to add as content. Then you create aDataHandler
object initialized with the URL object and pass it to the methodcreateAttachmentPart
.URL url = new URL("http://greatproducts.com/gizmos/img.jpg"); DataHandler dh = new DataHandler(url); AttachmentPart attachment = message.createAttachmentPart(dh); attachment.setContentId("gyro_image"); message.addAttachmentPart(attachment);You might note two things about the previous code fragment. First, it sets a header for Content-ID with the method
setContentId
. This method takes aString
that can be whatever you like to identify the attachment. Second, unlike the other methods for setting content, this one does not take aString
for the Content-Type. This method takes care of setting the Content-Type header for you, which is possible because one of the things aDataHandler
object does is determine the data type of the file it contains.Accessing an AttachmentPart Object
If you receive a message with attachments or want to change an attachment to a message you are building, you will need to access the attachments. When it is given no argument, the method
SOAPMessage.getAttachments
returns ajava.util.Iterator
object over all theAttachmentPart
objects in a message. The following code prints out the content of eachAttachmentPart
object in theSOAPMessage
objectmessage
.java.util.Iterator it = message.getAttachments(); while (it.hasNext()) { AttachmentPart attachment = it.next(); Object content = attachment.getContent(); String id = attachment.getContentId(); System.out.print("Attachment " + id + " contains: " + content); System.out.println(""); }Summary
You have now used the basic JAXM API and seen how to create and send SOAP messages as a standalone client and as a client using a messaging provider. You have added content to a SOAP header and a SOAP body and also created attachments and given them content. In addition, you have seen how to retrieve the content from the SOAP part and from attachments.
Home TOC |
![]() ![]() ![]() |