Oracle® Application Server Advanced Web Services Developer's Guide 10g Release 3 (10.1.3) B25603-01 |
|
![]() Previous |
![]() Next |
This chapter has the following sections.
This section contains the following subsections.
Oracle Application Server Web Services enables you to pass Multipurpose Internet Mail Extension (MIME) attachments with SOAP messages. The SOAP with Attachments (SWA) specification defines the SOAP messages with attachments that are supported by OracleAS Web Services. You can find the SOAP with Attachments specification at this Web site:
http://www.w3.org/TR/SOAP-attachments
In addition to the SOAP With Attachments specification, OracleAS Web Services also supports the Web Service-Interoperability (WS-I) Attachments Profile 1.0 that defines interoperable SOAP messages with attachments. In the interests of interoperability, the WS-I Attachments Profile adds certain constraints to the SWA specification. The profile also defines a new schema type, swaRef
, for referencing MIME parts from within the SOAP message body. Using this schema type for sending interoperable SOAP messages with attachments is not mandated, nor does it guarantee conformance to the profile. The type is only an optional convenience mechanism. OracleAS Web Services support both the swaRef
type and plain SWA
for sending SOAP messages with MIME attachments. You can find the WS-I Attachments Profile 1.0 at this Web site:
http://www.ws-i.org/Profiles/AttachmentsProfile-1.0-2004-08-24.html
OracleAS Web Services supports both the SWA
and swaRef
formats and their handling is transparent to the developer.
The following list describes the main differences between swaRef
and SWA
.
swaRef
attachments are uniquely identified MIME attachments, referenced in the SOAP body by a URL. SWA
attachments are uniquely identified, but there is no standard way for referencing them from within a SOAP body.
SWA
MIME parts must be defined by a mime:content
element in the corresponding mime:part
. The following example illustrates a ClaimPhoto
JPEG file, referenced as a SWA in a mime:content
element.
<mime:part> <mime:content part="ClaimPhoto" type="image/jpeg"/> </mime:part>
In contrast, swaRef
attachments should not be defined in the mime:content
element. Instead, they should be referenced in the soapbind:body
of the wsdl:binding
. The following example illustrates the ClaimDetail
file referenced as a swaRef
in the soapbind:body
element. Note that the file is referenced by a URL.
<mime:part> <soapbind:body use="literal" parts="ClaimDetail" namespace="http://example.com/mimetypes"/> </mime:part>
SWA
attachments are mapped to a corresponding Java type based on the MIME content type defined in the WSDL. For example, if the MIME content type is image/jpeg
, a java.awt.Image
will be used to represent the attachment. In contrast, swaRef
will always be mapped to javax.xml.soap.AttachmentPart
.
The swaRef
type allows MIME attachments to be referenced by a URL within the SOAP body. WS-I publishes a public schema which defines the swaRef
type. The public schema is defined by the following XSD:
http://ws-i.org/profiles/basic/1.1/xsd/
For more information on how to use this type to define attachments in a WSDL, see Section 4.4 of the WS-I Attachments Profile 1.0.
Note: Only RPC-literal and document-literal Web services are supported by the WS-I Attachments Profile 1.0. Thus, only those types of services can useswaRef . |
OracleAS Web Services support both top down and bottom up development of Web services using MIME attachments with swaRef
.
You can use WebServicesAssembler to assemble a Web service top down that can process and generate swaRef
MIME attachments. One of the ways in which you could do this is to provide a WSDL that contains swaRef
references as input to the genInterface
command. This command generates a service endpoint interface containing methods with parameters that will be passed as attachments.
Implementing the generated service endpoint interface includes working with classes and methods in the oracle.webservices.attachments
package. "Understanding the Streaming Attachments API" describes this API.
The following general steps describe how to assemble a Web service top down that exposes methods that pass swaRef
MIME attachments.
Provide a WSDL from which you want to assemble a Web service.
Enter the import statement for the swaRef
XSD in the WSDL. The following is an example import statement.
<xsd:import namespace="http://ws-i.org/profiles/basic/1.1/xsd" schemaLocation="http://ws-i.org/profiles/basic/1.1/xsd"/>
For each part in the wsdl:message
that needs to be a swaRef
attachment, set the type
attribute to the swaRef
complex type in the imported schema. An example of setting swaRef
to a complex type is type="wsi:swaRef"
. "Constructing a WSDL with swaRef Attachments" provides an example of a WSDL that references a swaRef
attachment.
Note: For document-literal services you should define an element in the schema with the typewsi:swaRef and reference that element in the wsdl:message part. This is because the Basic Profile requires document-literal message parts to reference elements, not types.
In the following example, the <!--This is defined in the schema section of the WSDL--> <xsd:element name="Status" type="wsi:swaRef" /> <!--This is the message part that references the swaRef element--> <wsdl:message name="replacePhotoResponse"> <wsdl:part name="status" type="types:Status"/> </wsdl:message> |
Use the WSDL as input to the WebServicesAssembler genInterface
command. Following is a sample genInterface
command.
java -jar wsa.jar genInterface -wsdl mySwaRefWsdl -output c:\appDir
This command generates a service endpoint interface with methods that handle swaRef
attachments and a Java class for each complexType
in the WSDL. The AttachmentPart
class will be used for all instances of swaRef
.
"Implementing a Service Endpoint Interface with Attachments" illustrates a sample generated service endpoint interface.
Implement the generated service endpoint interface.
In the implementation class, methods that receive attachments will have an AttachmentPart
parameter while methods that send swaRef
attachments will have AttachmentPart
as the return type. As part of the implementation of the methods, create a new instance of the AttachmentPart
and add an attachment using the setContent
method. "Creating a New Instance of AttachmentPart" provides an example of creating an instance of AttachmentPart
.
Example 2-4 illustrates the implementation of a generated service endpoint interface, with code that creates a new instance of AttachmentPart
.
A WSDL that uses swaRef
attachments must have the following characteristics.
Each part of the wsdl:message
that must be a swaRef
attachment must set its type attribute to the swaRef
complex type in the imported schema (or the element attribute set to an element that is of type swaRef
for document-literal services).
The swaRef
attachment should be referenced in the soapbind:body
of the wsdl:binding
. Example 2-1 illustrates the format of the swaRef
reference. The soapbind:body
element has three attributes. The use
attribute indicates whether the message format is literal or encoded. The parts
attribute indicates the part of the SOAP message that the attachment references and the namespace
attribute indicates the attachment.
Example 2-2 illustrates a WSDL that contains a swaRef
reference that can be used as input to genInterface
. The ClaimDetailType
complex type which is referenced by the ClaimDetail
part of the ClaimIn
message has an element ClaimForm
that is of type swaRef
. The ClaimDetail
part is referenced in the soapbind:body
of the binding as opposed to a mime:content
element which is not referenced as part of the SOAP body. The elements described in the preceding list, as well as the xsd:import
statement for the swaRef
schema, are highlighted in bold.
Example 2-2 WSDL that References a swaRef Attachment
<?xml version="1.0"?> <wsdl:definitions xmlns:types="http://example.com/mimetypes" xmlns:ref="http://ws-i.org/profiles/basic/1.1/xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapbind="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://example.com/mimewsdl" xmlns:tns="http://example.com/mimewsdl"> <wsdl:types> <xsd:schema targetNamespace="http://example.com/mimetypes" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:import namespace="http://ws-i.org/profiles/basic/1.1/xsd" schemaLocation="http://ws-i.org/profiles/basic/1.1/xsd"/> <xsd:complexType name="ClaimDetailType"> <xsd:sequence> <xsd:element name="Name" type="xsd:string"/> <xsd:element name="ClaimForm" type="ref:swaRef"/> </xsd:sequence> </xsd:complexType> </xsd:schema> </wsdl:types> <wsdl:message name="ClaimIn"> <wsdl:part name="ClaimDetail" type="types:ClaimDetailType"/> </wsdl:message> <wsdl:message name="ClaimOut"> <wsdl:part name="ClaimRefNo" type="ref:swaRef"/> </wsdl:message> <wsdl:portType name="ClaimPortType"> <wsdl:operation name="SendClaim"> <wsdl:input message="tns:ClaimIn"/> <wsdl:output message="tns:ClaimOut"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="ClaimBinding" type="tns:ClaimPortType"> <soapbind:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="SendClaim"> <soapbind:operation soapAction="http://example.com/soapaction"/> <wsdl:input> <mime:multipartRelated> <mime:part> <soapbind:body use="literal" parts="ClaimDetail" namespace="http://example.com/mimetypes"/> </mime:part> </mime:multipartRelated> </wsdl:input> <wsdl:output> <mime:multipartRelated> <mime:part> <soapbind:body use="literal" namespace="http://example.com/mimetypes"/> </mime:part> </mime:multipartRelated> </wsdl:output> </wsdl:operation> </wsdl:binding> </wsdl:definitions>
From this WSDL, the genInterface
command generates a service endpoint interface with swaRef
attachments, and a Java class for each complexType
in the WSDL. The AttachmentPart
class will be used for all instances of swaRef
.
For example, WebServicesAssembler will generate a Java class for the ClaimDetail
complex type. Its claimForm
parameter, which is of type swaRef
in the WSDL, will be generated as type AttachmentPart
in the Java code. The following code sample illustrates part of the class signature.
public class ClaimDetail{ private String name; private javax.xml.soap.AttachmentPart claimForm; ... }
Given a WSDL with references to swaRef
attachments, WebServicesAssembler generates a service endpoint interface that contains a Java class for each complexType
in the WSDL. It also contains Java methods that return a java.xml.soap.AttachmentPart
for each WSDL operation that has a swaRef
in the output method.
An implementation of a generated service endpoint interface must create a new instance of AttachmentPart
. OracleAS Web Services uses the AttachmentPart
class for creating and accessing swaRef
attachments. Since AttachmentPart
is an abstract class, it cannot be instantiated directly. You must create a new instance of AttachmentPart
as a part of the implementation of methods that send attachments.
Example 2-3 illustrates a generated service endpoint interface and Example 2-4 illustrates its implementation. In the generated service endpoint interface in Example 2-3, the sendClaim
method sends an attachment as a return parameter.
Example 2-3 Sample Generated Service Endpoint Interface with an Attachment
package oracle.j2ee.ws.client.attachments; public interface claimPortType extends java.rmi.Remote{ public AttachmentPart sendClaim(ClaimDetail claimDetail) throws java.rmi.RemoteException; }
The implementation class in Example 2-4 creates a new instance of AttachmentPart
in the sendClaim
method. "Creating a New Instance of AttachmentPart" describes how to use the SAAJ API to create a new instance of AttachmentPart
.
Once the AttachmentPart
instance is created, an image or any other object can be added using the setContent(Object obj, String mimeType)
method. The first parameter of the method takes the object to be attached and the second parameter specifies the MIME content type of that object. For example, if a GIF image is being sent, the setContent
method would be setContent(newPhoto,"image/gif")
.
Example 2-4 Implementation of a Service Endpoint Interface
public class ClaimPortTypeImpl implements ClaimPortType { public AttachmentPart sendClaim(ClaimDetail claimDetail) throws RemoteException{ AttachmentPart impl = null; try{ MessageFactory factory = MessageFactory.newInstance(); SOAPMessage message = factory.createMessage(); impl = message.createAttachmentPart(); } catch(SOAPException ex){ return null; } return impl; }
This section illustrates the basic code for creating a new instance of AttachmentPart
. OracleAS Web Services uses the AttachmentPart
class for creating and accessing swaRef
attachments.
Example 2-5 illustrates sample code that uses the SAAJ API to create a new instance of AttachmentPart
. Note that the createAttachmentPart
method of javax.xml.soap.SOAPMessage
takes an object and a MIME type as parameters.
Example 2-5 Creating a New Instance of AttachmentPart
javax.xml.soap.MessageFactory mf = javax.xml.soap.MessageFactory.newInstance(); javax.xml.soap.SOAPMessage message = mf.createMessage(); javax.xml.soap.AttachmentPart ap = message.createAttachmentPart(attachmentObj,"image/jpeg");
The generated service interface can now be implemented and swaRef
attachments can be sent and received using AttachmentPart
from the SAAJ API.
You can use WebServicesAssembler to assemble a Web service bottom up that can pass swaRef
MIME attachments. One of the ways in which you could do this is to provide a Java class that contains method parameters that represent attachments to the assemble
or genWsdl
commands. These commands produce a WSDL with references to swaRef
attachments.
Writing and implementing the Java classes that contain attachments includes working with classes and methods in the oracle.webservices.attachments
package. "Understanding the Streaming Attachments API" describes this API.
Note: WebServicesAssembler will not be able to assemble a Web service that can passswaRef MIME attachments if you specify an RPC-encoded message format. To assemble the service, you must select a different format. |
The following general steps describe how to assemble a Web service bottom up that exposes elements in the WSDL that represent swaRef
MIME attachments.
Provide the Java class you want to expose as a Web service.
In the class file, any methods that use parameters that represent attachments should be identified as type AttachmentPart
. In your implementation of the methods that use attachments, create a new instance of AttachmentPart
. "Creating a New Instance of AttachmentPart" illustrates sample code that uses the SAAJ API to create this.
"Writing a Service Endpoint Interface that Handles Attachments" illustrates a service endpoint interface with a method that passes attachments.
Use the WebServicesAssembler to generate a WSDL file.
Use the assemble
command if you want to assemble the WSDL and all of the service artifacts for a Web service.
Use the genWsdl
command if you want to generate only the WSDL file.
The generated WSDL file will contain an <xsd:element name="..." type="ref:swaRef"/>
element for each parameter in the Java class identified as type AttachmentPart
.
"Assembling a WSDL File with swaRef Attachment References" illustrates a WSDL file generated with the genWsdl
command that contains swaRef
attachment references.
If you used the genWsdl
command to generate the WSDL, you can now inspect the file.
If you used the assemble
command to assemble the Web service, you can now deploy the service, generate a proxy, and write a client. "Assembling a Web Service with Java Classes" in the Oracle Application Server Web Services Developer's Guide provides more information on these steps.
If methods in your service endpoint interface pass attachments, and you want the attachments to be passed as a swaRef
, then the parameters that represent the attachments must be of type AttachmentPart
. In bottom up Web service assembly scenarios, WebServicesAssembler generates a swaRef
type reference into the WSDL for every AttachmentPart
type it encounters in an implementation class or interface.
Example 2-6 illustrates an interface that contains a parameter, claimDetail
, of type AttachmentPart
. When passed to WebServicesAssembler using the genWsdl
or assemble
command, this interface yields a WSDL file.
Example 2-7 illustrates a fragment of the WSDL file, displaying only the type definitions. The example assumes that the interface in Example 2-6 was used as input to the genWsdl
command to generate the WSDL with document-wrapped style. The WSDL fragment identifies the claimDetail
element as being of type swaRef
(highlighted in bold).
Note that the same WSDL fragment would be created if the assemble
command was used to generate the WSDL. This is the default behavior when WebServicesAssembler encounters the AttachmentPart
data type.
Example 2-7 WSDL Fragment, Displaying only Type Definitions
... <xsd:import namespace="http://ws-i.org/profiles/basic/1.1/xsd" /> <xsd:complexType name="sendClaimType"> <xsd:sequence> <xsd:element name="id" type="xsd:string"/> <xsd:element name="claimDetail" type="ref:swaRef"/> </xsd:sequence> </xsd:complexType> </xsd:schema> </wsdl:types> ...
SWA attachments refer to attachments that conform to the SOAP With Attachments (SWA) specification. Currently, WebServicesAssembler supports only top down assembly of Web services with WSDL files that contain SWA
attachments. SWA
MIME parts are defined in the <wsdl:binding>
clause of the WSDL. The attachment is defined by a mime:content
element in the corresponding mime:part
.
Example 2-8 illustrates the format of the mime:content
element and its part
and type
attributes. The part
attribute identifies the part of the SOAP message to which the attachment belongs. The type
attribute identifies the content type in the attachment.
Example 2-8 SWA Attachment Referenced in the mime:content Element
<mime:part> <mime:content part="string" type="content type"/> </mime:part>
WebServicesAssembler processes each mime:content
element found in the WSDL file and maps it to a Java type that corresponds to the MIME-content type.
Table 2-1 displays the MIME content types and corresponding Java types to which they will be mapped. The default type for any MIME-content type that is not recognized is javax.activation.DataHandler
.
Table 2-1 Mapping Content Types for SWA Attachments
Content Type | Java Type |
---|---|
image/jpeg, image/gif, image/tif |
|
text/plain, application/plain |
|
text/xml |
|
Provide the WSDL from which you want to generate a Web service.
Each element that represents a SWA attachment must appear in a <mime:content...>
element in the <wsdl:binding...>
clause of the WSDL.
In Example 2-9, a photo
JPEG attachment appears in a <mime:content...>
element:
<mime:part> <mime:content part="photo" type="image/jpeg"/> </mime:part>
Use the WSDL as input to the WebServicesAssembler genInterface
command. Following is a sample genInterface
command.
java -jar wsa.jar genInterface -wsdl mySwaWsdl -output c:\appDir
The genInterface
command generates a service endpoint interface with parameters that represent SWA
attachments and a Java class for each complexType
in the WSDL. A Java class will be used for all instances of SWA
attachments.
Example 2-10 illustrates a generated service endpoint interface with a parameter that represents a SWA attachment as a java.awt.Image
Java data type.
Implement the generated service endpoint interface.
Example 2-9 illustrates a WSDL that contains a SWA
reference that can be used as input to genInterface
. Note that this WSDL example omits the wsdl:service
element for the sake of brevity.
Example 2-9 WSDL that References a SWA Attachment
<wsdl:definitions name="PhotoCatalogService" targetNamespace="http://examples.com/PhotoCatalog" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:types="http://examples.com/PhotoCatalog/types" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://examples.com/PhotoCatalog"> <wsdl:message name="addPhotoRequest"> <wsdl:part name="photo" type="xsd:hexBinary"/> </wsdl:message> <wsdl:message name="addPhotoResponse"> <wsdl:part name="status" type="xsd:string"/> </wsdl:message> <wsdl:message name="replacePhotoRequest"> <wsdl:part name="oldPhoto" type="xsd:string"/> <wsdl:part name="newPhoto" type="xsd:hexBinary"/> </wsdl:message> <wsdl:message name="replacePhotoResponse"> <wsdl:part name="status" type="xsd:string"/> </wsdl:message> <wsdl:portType name="PhotoCatalog"> <wsdl:operation name="addPhoto"> <wsdl:input message="tns:addPhotoRequest"/> <wsdl:output message="tns:addPhotoResponse"/> </wsdl:operation> <wsdl:operation name="replacePhoto"> <wsdl:input message="tns:replacePhotoRequest"/> <wsdl:output message="tns:replacePhotoResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="PhotoCatalogBinding" type="tns:PhotoCatalog"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="addPhoto"> <wsdl:input> <mime:multipartRelated> <mime:part> <soap:body use="literal"/> </mime:part> <mime:part> <mime:content part="photo" type="image/jpeg"/> </mime:part> </mime:multipartRelated> </wsdl:input> <wsdl:output> <mime:multipartRelated> <mime:part> <soap:body use="literal"/> </mime:part> <mime:part> <mime:content part="status" type="text/plain"/> <mime:content part="status" type="text/xml"/> </mime:part> </mime:multipartRelated> </wsdl:output> </wsdl:operation> <wsdl:operation name="replacePhoto"> <wsdl:input> <mime:multipartRelated> <mime:part> <soap:body parts="oldPhoto" use="literal"/> </mime:part> <mime:part> <mime:content part="newPhoto" type="image/jpeg"/> </mime:part> </mime:multipartRelated> </wsdl:input> <wsdl:output> <soap:body parts="status" use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> </wsdl:definitions>
Given the WSDL displayed in Example 2-9, the WebServicesAssembler genInterface
command generates the interface in Example 2-10. The photo
and newPhoto
parameters are generated with the Java data type java.awt.Image
because their mime:content
is defined with image/jpeg
. An implementation of the interface can now pass JPEG files as attachments for the photo
part. This is the same for RPC-literal and document-literal (wrapped and bare).
Example 2-10 Generated Interface with a SWA Attachment
public interface PhotoCatlog extends java.rmi.Remote{ public javax.activation.Datahandler addPhoto (java.awt.Image photo) throws java.rmi.RemoteException; public String replacePhoto(java.awt.Image newPhoto, String oldPhoto) throws java.rmi.RemoteException; }
This section describes how to add MIME type attachments to SOAP fault messages.
Note: In OracleAS Web Services, you can add only MIME type attachments to SOAP fault messages. |
The attachment is added to the fault message when the Web service implementation class throws an exception. The WS-I Attachments Profile 1.0 specifies that a SOAP fault can contain attachments only if a <mime:part>
element appears in an operation's output message in the WSDL. Thus, if custom faults appear in a WSDL operation
that has an output message with an attachment, WebServicesAssembler generates a special exception class that handles attachments in the fault.
The WSDL fragment in Example 2-11 illustrates the <mime:part>
in the <wsdl:operation>
clause that declares that an operation can output MIME content. The namespace
attribute is required only when you are working with RPC-literal messages. The WSDL fragment also illustrates the <wsdl:fault>
element that defines the fault that the operation can throw.
Example 2-11 WSDL Fragment, that Defines a SOAP Fault
<wsdl:operation> ... <wsdl:output> <mime:multipartRelated> <mime:part> <soap:body parts="string" use="literal|encoded" [namespace="URL"]/> </mime:part> </mime:multipartRelated> </wsdl:output> <wsdl:fault name="string"> <soap:fault name="string" use="literal|encoded"/> </wsdl:fault> </wsdl:operation>
When WebServicesAssembler encounters a <wsdl:fault>
element, it generates a com.examples.types.
Fault_NameType
exception class, where Fault_Name is the value of the name
attribute in the wsdl:fault
element.
An implementation of a method that throws a generated fault class must also include an implementation of a new instance of the class. It must also include code to add the attachment to the exception.
Writing and implementing the Java classes that contain attachments includes working with classes and methods in the oracle.webservices.attachments
package. "Understanding the Streaming Attachments API" describes this API.
Note: Faults with attachments can be added to a Web service only when you are assembling it from a WSDL (top down). They cannot be added when assembling a Web service bottom up. |
The following general steps describe how to add attachments to SOAP fault messages and generate them into the service endpoint interface.
Provide the WSDL that you want to work with.
Edit the WSDL operation that you want to throw a fault with attachment content.
Declare the output element that will contain attachment content in the <wsdl:output.../>
clause. The clause must contain <mime:multipartRelated>
content.
Define a <wsdl:fault.../>
element.
"Specifying SOAP Faults with Attachments in the WSDL" provides an example of a WSDL that has been edited to include the wsdl:output
and wsdl:fault
elements.
Use genInterface
to generate a service endpoint interface.
java -jar wsa.jar genInterface -wsdl myWsdl -output c:\appDir
The methods in the service endpoint interface that use the attachment data will have a parameter that takes an attachment
data type. The method will throw an exception that implements oracle.webservices.attachments.AttachmentFault
.
Implement the interface.
In the implementation, include code to perform the following tasks.
Create a new instance of the exception that implements oracle.webservices.attachments.AttachmentFault
Add an attachment to the exception with the addAttachment
method.
"Implementing a Method that Throws Faults with Attachments" illustrates sample code that creates a new instance of the exception and adds the attachment to it.
After this step, you can compile the interface and the implementation, deploy the service, and generate the client code. "Assembling a Web Service from a WSDL" in the Oracle Application Server Web Services Developer's Guide provides more detail on the steps for assembling and deploying a Web service top down.
To specify a SOAP fault that can throw attachment content, the WSDL operation must identify the namespace of the attachment content, whether its message use is literal or encoded, and the part of the SOAP message it belongs to. The WSDL operation is specified in the <mime:part>
of the <wsdl:operation>
clause.
The WSDL fault itself must identify its name and whether its message use is literal or encoded. The <wsdl:fault>
clause appears as a peer to the WSDL input and WSDL output clauses.
Example 2-12 illustrates a WSDL fragment for the replacePhoto
binding operation with wsdl:output
and wsdl:fault
elements. Because wsdl:output
identifies MIME content, the fault message defined by wsdl:fault
will be able to contain attachments.
Example 2-12 WSDL Fragment, Displaying only Port Types and Binding Declarations
<wsdl:operation name="replacePhoto"> <wsdl:input> <mime:multipartRelated> <mime:part> <soap:body parts="oldPhoto" use="literal" namespace="http://examples.com/PhotoCatalog"/> </mime:part> <mime:part> <mime:content part="newPhoto" type="image/jpeg"/> </mime:part> </mime:multipartRelated> </wsdl:input> <wsdl:output> <mime:multipartRelated> <mime:part> <soap:body parts="status" use="literal" namespace="http://examples.com/PhotoCatalog"/> </mime:part> </mime:multipartRelated> </wsdl:output> <wsdl:fault name="InvalidPhoto"> <soap:fault name="InvalidPhoto" use="literal"/> </wsdl:fault> </wsdl:operation>
A method in the generated service endpoint interface that can throw a fault with attachment content contains a parameter that takes an attachment data type and throws a exception that implements oracle.webservices.attachments.AttachmentFault
. An implementation of the method must create a new instance of the exception. It must also add the attachment to the exception. The oracle.webservices.attachments
package provides an FaultWithAttachments.addAttachment
method to do this. "Understanding the Streaming Attachments API" describes this method.
Example 2-13 illustrates an implementation of the replacePhoto
operation defined by the WSDL fragment in Example 2-12. The InvalidPhoto
fault defined in the WSDL is mapped to the com.examples.types.InvalidPhotoType
exception class.
As required, the implementation of replacePhoto
creates a new instance of the InvalidPhotoType
exception. It also adds the attachment to the exception with the FaultWithAttachments.addAttachment
method. The InvalidPhotoType
can then be thrown as an exception which causes it to be transmitted as a SOAP fault with attachments.
Example 2-13 Implementing a Method that Throws Faults with Attachments
public AttachmentPart replacePhoto(PhotoInfoType oldPhoto, Image newPhoto) throws RemoteException,com.examples.types.InvalidPhotoType { if(newPhoto == null){ return null; } if(oldPhoto.getPhotoID() == -1){ InvalidPhotoType typeException = new InvalidPhotoType(-1,"InvalidPhotoType","The PhotoId specified is invalid"); try{ Image image = javax.imageio.ImageIO.read(new File("myImage")); typeException.addAttachment(image,"image/jpeg"); }catch(Exception e){ throw new RemoteException("unexpected exeption",e); } throw typeException; } AttachmentPart impl = null; try{ MessageFactory factory = MessageFactory.newInstance(); SOAPMessage message = factory.createMessage(); impl = message.createAttachmentPart(); }catch(SOAPException ex){ return null; } return impl; }
A J2SE or J2EE Web service client can be coded to retrieve SOAP faults with attachments thrown by the service. The oracle.webservices.attachments
package provides methods that a client can use to retrieve attachment content from the fault. For example, the getAttachments
method can be used to get an iterator of the list of attachments in the fault. The hasAttachments
method can be used to query if a fault has an attachment.
Example 2-14 illustrates a client stub, photoCatalog
, that can retrieve attachment content. The example assumes that the oldPhoto
and newPhoto
parameters have been previously defined, and the InvalidPhotoType
exception implements oracle.webservices.attachments.AttachmentFault
. Since InvalidPhotoType
implements AttachmentFault
, it is a SOAP fault that can contain attachments.
The hasAttachments
method tests for attachments in the fault. If this method returns true
, the SOAP fault has attachments. The getAttachments
method retrieves all of the attachments in a SOAP fault. This method returns an iterator containing an AttachmentPart
object for each attachment in the SOAP fault.
Example 2-14 Web Service Client with Code for Retrieving Attachments
public class MyClientExample{ PhotoCatalog photoCatalog = getPhotoCatalogPortType(); //create a client stub for the web service try{ //assuming oldPhoto and newPhoto are defined photoCatalog.replacePhoto(oldPhoto, newPhoto); // assuming InvalidPhotoType implements AttachmentFault }catch(InvalidPhotoType type){ if(type.hasAttachments()){ java.util.Iterator it = type.getAttachments(); AttachmentPart p = (AttachmentPart)it.next(); //do something useful with the attachment. } }
OracleAS Web Services enables you to pass large attachments as a stream. As opposed to the JAX-RPC API, which treats attachments as if they were entirely in memory, streams make the programming model more efficient to use. It also enhances performance and scalability in that there is no need to load the attachment into memory before service execution.
Like embedded attachments, streamed attachments conform to the multipart-MIME binary format. On the wire, messages with streamed attachments are identical to any other SOAP message with attachments.
Example 2-15 provides a sample message with a streamed attachment. The first "part" in the message is the SOAP envelope (<SOAP-ENV:Envelope...
). The second "part" is the attachment, in this case, myImage.gif
.
Example 2-15 Sample Message with a Streamed Attachment
MIME-Version: 1.0 Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml; Content-Description: This is the optional message description. --MIME_boundary Content-Type: text/xml; charset=UTF-8 Content-Transfer-Encoding: 8bit Content-ID: NotSure/DoesntMatter <?xml version='1.0' ?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> .. <DocumentName>MyImage.gif</DocumentName> .. </SOAP-ENV:Body> </SOAP-ENV:Envelope> --MIME_boundary Content-Type: image/gif Content-Transfer-Encoding: binary Content-ID: AnythingYoudLike ...binary GIF image... --MIME_boundary--
There are some limitations on the use of streamed attachments in OracleAS Web Services.
A Web service port can send only embedded attachments or streamed attachments; not both.
Handlers cannot obtain access to streamed attachments.
Any message with streamed attachments will appear to all handlers as a SOAP message without attachments.
Streaming is enabled by adding an extra parameter to each service or stub operation that wants to stream attachments. This parameter must be of type Attachments
. The Attachments
interface provides methods for reading incoming attachment streams (service requests or client responses) and for adding outgoing attachment streams (service responses or client requests).
The Attachments
interface belongs to the oracle.webservices.attachments
package. "Understanding the Streaming Attachments API" describes this package.
This section describes how to assemble a Web Service that uses streaming attachments.
Assembling a Web Service that Supports Streaming Attachments Bottom Up
Assembling a Web Service that Supports Streaming Attachments Top Down
The model for assembling a Web service bottom up that supports streaming attachments, is the same as any other service based on Java classes. "Assembling a Web Service with Java Classes" in the Oracle Application Server Web Services Developer's Guide provides more information on assembling a Web service bottom up with Java classes.
Write a public interface that contains the remote methods that you want to expose as a service. In this case, one or more of the methods will use the Attachment API.
"Writing an Interface for Steaming Attachments" provides more information on this step.
Write the implementation of the service.
"Implementing a Service Interface that Uses Streaming Attachments" provides more information on this step.
Write the stub code for the Web service client. To use a stub to send or receive attachments, you must create the Attachments
object before the call.
"Writing Stub Code to Handle Streaming Attachments" provides more information on this step.
Generate the service artifacts by running the WebServicesAssembler with the assemble
command.
Deploy the service and bind the application.
Generate the client-side code.
Compile and run the client.
If you want to stream attachments as a part of your Web service, then at least one of the methods within the service interface must contain a parameter of type Attachments
. The Attachments
type indicates objects will be streamed by OracleAS Web Services.
Example 2-16 illustrates the service interface for a Web service that stores large image files in a local database. The request includes an image name, a description, and the image to be stored. Note that the attachments
parameter of type Attachments
indicates that the image will be streamed.
Example 2-16 Service that Uses Streaming Attachments
public interface ImageStore extends java.rmi.Remote { public void storeImage (String name, String desc, Attachments attachments) throws java.rmi.RemoteException; }
If you use this interface to generate a Web service bottom up, WebServicesAssembler will detect the parameter of type Attachments
. Support for streaming attachments will automatically be generated into the Web service. Example 2-18 illustrates the relevant parts of the WSDL generated by WebServicesAssembler.
Implementations of interfaces that include data as streaming attachments use the methods and classes of the oracle.webservices.attachments
API to work with the attachment data.
Example 2-17 illustrates the implementation of the interface in Example 2-16 for a Web service that stores large image files in a local database. The implementation uses the getIncomingAttachments
method to capture the incoming streaming attachment as an Attachment
object. The getId
method retrieves the attachment's metadata and getInputStream
stores the stream image bytes.
Example 2-17 Service Implementation that Employs Streaming Attachments
class ImageStoreImpl { public void storeImage(String name, String desc, Attachments attachments) throws Exception { IncomingAttachments incomingAtts = attachments.getIncomingAttachments(); { if (incomingAtts == null || !incomingAtts.hasNextAttachment()) throw new Exception("Expected request attachments"); Attachment imageAtt = incomingAtts.nextAttachment(); String id = imageAtt.getId(); DataHandler dataHandler = imageAtt.getDataHandler(); InputStream imageStream = dataHandler.getInputStream(); //-- Store image metadata and stream image bytes if (incomingAtts.hasNextAttachment()) throw new Exception("Expected only one attachment"); } } }
The presence of the <stream-attachments>
extension (in the namespace http://oracle.com/schemas/webservices/streaming-attachments
) in the WSDL indicates that the Web service supports streaming attachments.
Example 2-18 illustrates the relevant parts of the WSDL that WebServicesAssembler generates from the interface in Example 2-16. The <stream-attachments>
element that identifies streaming is highlighted in bold. "WSDL Extensions for Streaming Attachments" contains more information about the <stream-attachments>
element and its schema.
Example 2-18 WSDL Elements for a Streaming Attachment
<message name="storeImageRequest">
<part name="name" type="string"/>
<part name="desc" type="string"/>
</message>
<portType name="ImageStorePortType">
<operation name="storeImage">
<input name="storeImageRequest" message="tns:storeImageRequest"/>
<output name="storeImageResponse" message="tns:storeImageResponse"/>
</operation>
</portType>
<binding name="ImageStoreBinding" type="tns:ImageStorePortType">
<soap:binding style="rpc" />
<operation name="addPerson">
<soap:operation style="encoded" wsdl:required="true" />
<sa:stream-attachments name="attachments" />
<input name="storeImageRequest">
<soap:body use="encoded" />
</input>
<output name="storeImageResponse">
<soap:body use="encoded" />
</output>
</operation>
</binding>
The stub is the client side of the Web service. If the service wants to receive streamed attachments, the client must send them. If the server sends streamed attachments, the client must read them.
To handle streaming attachments, client code must create a new instance of an AttachementFactory
and create an Attachments
object. For a request attachment, the addAttachment
method can be used to add the attachment to the output stream.
For a response attachment, the client code must create a new instance of an AttachementFactory
and create an Attachments
object. The client can capture the attachments with the iterator methods in the IncomingAttachments
interface.
Example 2-19 illustrates stub code to store a streaming attachment. In the example, an AttachmentFactory
is instantiated with the newInstance
method and an Attachments
object is created with the createAttachments
method. The addAttachment
method adds the data to the output stream.
Example 2-19 Client Code to Store a Streaming Attachment
public void storeImageFile (String fileName) { //-- Create the attachment objects AttachmentFactory factory = AttachmentFactory.newInstance(); Attachments atts = factory.createAttachments(); Attachment imageAtt = factory.createAttachment (fileName, "image/gif", new FileInputStream(fileName)); atts.getOutgoingAttachments().addAttachment(imageAtt); storeImagePort.storeImage (fileName, "File stored at " + fileName, atts); }
Assembling a Web service that supports streaming attachments follows the general steps described in "Assembling a Web Service from a WSDL" in the Oracle Application Server Web Services Developer's Guide. This section summarizes these steps.
To support streaming attachments, you must also edit the WSDL to add the <stream-attachments>
element. Example 2-18 illustrates a WSDL that contains the <stream-attachments>
element.
Provide a WSDL from which the Web service will be generated.
Edit the WSDL to add the elements that allow the Web service to support streaming attachments. "WSDL Extensions for Streaming Attachments" describes the <stream-attachments>
element.
Use the WSDL as input to the WebServicesAssembler genInterface
command.
Compile the generated interface and type classes.
Write the Java Service Endpoint interface for the Web service you want to provide.
Compile the Java Service Endpoint interface.
Generate the service by running the WebServicesAssembler tool with the topDownAssemble
command.
Deploy the service.
Generate the client code.
Streaming attachments uses a WSDL extension, <stream-attachments>
, to notify the WebServicesAssembler tool that attachment data will be streamed. The extension can be used only at the binding operation level. The element is specified in an Oracle namespace and takes a single string attribute, name
. The name
attribute is used as the parameter name when generating Java classes and interfaces. Example 2-18 illustrates a WSDL that contains the <stream-attachments>
element. Example 2-20 illustrates the <stream-attachments>
schema.
Example 2-20 XML Schema for Streaming Attachments
<schema xmlns="http://www.w3.org/2000/10/XMLSchema" xmlns:sa="http://oracle.com/schemas/webservices/streaming-attachments" targetNamespace="http://oracle.com/schemas/webservices/streaming-attachments"> <element name="stream-attachments" type="sa:streamAttachemntsType"/> <complexType name="streamAttachemntsType"> <attribute name="name" type="string" use="required"/> </complexType> </schema>
The Attachments API provides a programmatic interface to streaming attachments. Streamed attachments are directional; they can be classified as "incoming" and "outgoing". Incoming streams can only be read and outgoing streams can only be written to. The API resides in the oracle.webservices.attachments
package. Table 2-2 summarizes the interfaces and classes in the Attachments API. The sections following the table provide more detail.
Table 2-2 Interfaces in the Attachments API
Interface or Class | Description |
---|---|
|
Root interface for managing attachments. This interface contains methods for storing attachments as either incoming or outgoing attachments. See "Interface for Attachments" for more information. |
|
Provides iterators to process incoming attachments. These can be request attachments on the server or response attachments on the client. See "Interface for Incoming Attachments" for more information. |
|
Collects outgoing attachments for streaming after the message is serialized. These can be request attachments on the client or response attachments on the server. See "Interface for Outgoing Attachments" for more information. |
|
The |
|
This factory class creates instances of |
Attachments
is the root interface for managing attachments. The getIncomingAttachments
method returns an IncomingAttachments
object. It returns null
if there are no incoming attachments. The getOutgoingAttachments
method always returns an OutgoingAttachments
object.
public interface Attachments { IncomingAttachments getIncomingAttachments(); OutgoingAttachments getOutgoingAttachments(); }
The IncomingAttachments
interface is used for request attachments on the server and for response attachments on the client. It is, essentially, an iterator over attachments. The interface includes a close
method that tells the runtime to flush any remaining attachments from the stream. This must be called after all attachments have been processed so the connection can be cleared for the next request.
interface IncomingAttachments { public boolean hasNextAttachment() throws IOException; public Attachment nextAttachment() throws IOException; public void close() throws IOException; }
The OutgoingAttachments
interface is used for request attachments on the client and for response attachments on the server. It collects attachments for streaming after the message is serialized. The interface includes an addAttachment
method to add attachments to the output stream. You can create attachments using the methods described in "Factory Class for Attachment Objects".
interface OutgoingAttachments { public void addAttachment (Attachment attachment); }
The Attachment
object consists of a String
ID to identify the attachment and a data handler to retrieve the data. It is used by the addAttachment
method in the OutgoingAttachments
interface to add an attachment to the output stream.
interface Attachment { public String getId(); public DataHandler getDataHandler(); }
The package provides a factory class for creating instances of Attachments
and Attachment
objects. When you are using streaming attachments in a stub, you must create the Attachments
object before you call the service.
abstract class AttachmentFactory { public Attachments createAttachments(); public Attachment createAttachment (String id, String contentType, InputStream attachmentStream); public Attachment createAttachment (String id, DataHandler handler); public static AttachmentFactory newInstance(); }
Direct Internet Message Encapsulation (DIME) is a format for streaming multi-part message attachments over the wire. DIME can be applied to SOAP messages with attachments. DIME separates each record, such as a SOAP message or attachment, with a simple binary SOAP header that describes the size and type of the payload. DIME also allows a given piece of payload to be broken into multiple records. This allows the sender to stream data through a buffer of constrained size.
Compared to the multipart-MIME encoding format which OracleAS Web Services uses by default, DIME requires much less processing effort to encode or decode.
OracleAS Web Services lets you choose between supporting interoperable DIME-encoded messages and messages with Oracle-proprietary DIME encoding. Interoperable DIME encoding for messages with attachments is implemented by adding extensions to the WSDL. Oracle-proprietary DIME encoding is implemented by allowing WebServicesAssembler to generate code that applies DIME encoding to all SOAP messages with attachments.
The following sections provide more detailed information on each of these techniques.
These WSDL extensions are an implementation of Microsoft's DIME support. This technique creates messages with attachments that are interoperable with other vendors, particularly Microsoft, who implement DIME extensions in the WSDL. The extensions cause any binary data in the envelope to be extracted and placed in attachments. These messages and their attachments are then encoded in DIME.
The WSDL extensions are defined in the "WSDL Extension for SOAP in DIME" specification. This specification is located at:
http://www.gotdotnet.com/team/xml_wsspecs/dime/WSDL-Extension-for-DIME.htm
The schema that defines the extensions is located at:
http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/
The specification defines a DIME element, <dime:message>
. If this element is added to the WSDL, then any binary data in the SOAP message is automatically removed and put into attachments. The message and its attachments are then sent in DIME format instead of the default multipart-MIME format.
The <dime:message>
element can be inserted into the <wsdl:input>
and/or <wsdl:output>
elements of a Web service operation bindings definition. Table 2-3 describes the attributes that <dime:message>
must include.
Table 2-3 <dime:message> Required Attributes
Attribute | Description |
---|---|
wsdl:required="true" |
Indicates that the presence of a WSDL is required. This attribute must be set to |
layout="uri" |
Specifies how the primary SOAP message references the attachments in a DIME message. The following are the possible values for the URI.
|
Example 2-21 illustrates a WSDL skeleton with the extensions for DIME encoding highlighted in bold.
Example 2-21 WSDL Skeleton, with the Extensions for DIME Encoding
<wsdl:definitions ...> <wsdl:binding ...> <soap:binding .../> <wsdl:operation ...> <soap:operation .../> <wsdl:input> <dime:message layout="uri" wsdl:required="true"/>? <-- extensibility elements --> </wsdl:input> <wsdl:output> <dime:message layout="uri" wsdl:required="true"/>? <-- extensibility elements --> </dime:message> </wsdl:output> </wsdl:operation> </wsdl:binding> </wsdl:definitions>
The WebServicesAssembler supports the DIME-encoded format by providing a useDimeEncoding
argument. This argument will apply DIME encoding to all streaming SOAP messages with attachments in a generated service or stub.
The messages generated with the useDimeEncoding
argument are not interoperable and are incompatible with non-Oracle Web services or earlier versions of Oracle Application Server. Generating a Web service with this argument is useful for in-house projects where performance is key.
See "useDimeEncoding" in "General Web Services Assembly Arguments" in the Oracle Application Server Web Services Developer's Guide for more information on this argument.
For information on enabling WSIF clients to handle message attachments, see "Adding Message Attachments in WSIF".
For more information on:
enabling WSIF clients to handle attachments, see Web Services Invocation Framework, see Chapter 9, "Using Web Services Invocation Framework".
assembling a Web service top down, see "Assembling a Web Service from a WSDL" in the Oracle Application Server Web Services Developer's Guide.
using Java classes to assemble a Web service, see "Assembling a Web Service with Java Classes" in the Oracle Application Server Web Services Developer's Guide.
using EJBs to assemble a Web service, see "Assembling a Web Service with EJBs" in the Oracle Application Server Web Services Developer's Guide.
using JMS topics and destinations to assemble a Web service, see "Assembling Web Services with JMS Destinations" in the Oracle Application Server Web Services Developer's Guide.
using database resources, such as PL/SQL packages, SQL queries, DML statements, Oracle Streams AQ, or server-side Java classes, to assemble a Web service, see "Assembling Database Web Services" in the Oracle Application Server Web Services Developer's Guide.
assembling a J2EE Web Service client, see "Assembling a J2EE Web Service Client" in the Oracle Application Server Web Services Developer's Guide.
assembling a J2SE Web service client, see "Assembling a J2SE Web Service Client" in the Oracle Application Server Web Services Developer's Guide.
using WebServicesAssembler commands to assemble Web service artifacts, see "Using WebServicesAssembler" in the Oracle Application Server Web Services Developer's Guide.