Skip Headers
Oracle® Application Server Advanced Web Services Developer's Guide
10g Release 3 (10.1.3)
B25603-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

2 Working with Message Attachments

This chapter has the following sections.

Working with MIME Attachments

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.

Assembling a Web Service Using swaRef MIME Attachments

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 use swaRef.

OracleAS Web Services support both top down and bottom up development of Web services using MIME attachments with swaRef.

Assembling a Web Service Top Down

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.

  1. Provide a WSDL from which you want to assemble a Web service.

  2. 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"/>
    
    
  3. 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 type wsi: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 wsdl:part name="status" in the message part references the xsd:element name="Status" of type swaRef in the schema section of the WSDL.

    <!--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>
    

  4. 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.

  5. 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.

Constructing a WSDL with swaRef Attachments

A WSDL that uses swaRef attachments must have the following characteristics.

  • The WSDL must import the swaRef XSD file.

  • 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-1 swaRef Attachment Referenced in the soapbind:body Element

    <mime:part>
       <soapbind:body use="literal|encoded" parts="string" namespace="URL"/>
    </mime:part>
    
    

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;
   ...
}
Implementing a Service Endpoint Interface with Attachments

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;
}
Creating a New Instance of AttachmentPart

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.

Assembling a Web Service Bottom Up

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 pass swaRef 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.

  1. 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.

  2. 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.

  3. 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.

Writing a Service Endpoint Interface that Handles Attachments

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-6 Service Endpoint Interface with a Method that Passes Attachments

public interface ClaimServicePortType extends java.rmi.Remote{
   public String sendClaim(int id, AttachmentPart claimDetail) throws RemoteException;
   }
Assembling a WSDL File with swaRef Attachment References

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>
...

Assembling a Web Service Using SWA MIME Attachments

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

java.awt.Image. If these content types are used in combination, or if image/* is specified, then they are mapped to the java.activation.DataHandler Java type.

text/plain, application/plain

java.lang.String. If these types are used in combination, then they are mapped to the java.activation.DataHandler Java type.

text/xml

java.activation.DataHandler


  1. Provide the WSDL from which you want to generate a Web service.

  2. 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>
    
    
  3. 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.

  4. 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;
   }

Adding SOAP Faults with MIME Attachments

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.

  1. Provide the WSDL that you want to work with.

  2. Edit the WSDL operation that you want to throw a fault with attachment content.

    1. Declare the output element that will contain attachment content in the <wsdl:output.../> clause. The clause must contain <mime:multipartRelated> content.

    2. 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.

  3. 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.

  4. Implement the interface.

    In the implementation, include code to perform the following tasks.

    1. Create a new instance of the exception that implements oracle.webservices.attachments.AttachmentFault

    2. 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.

Specifying SOAP Faults with Attachments in the WSDL

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>

Implementing a Method that Throws Faults with Attachments

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;
    }

Using SOAP Faults with Attachments on the Client

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.
    }
}

Working with Streaming Attachments

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.


Note:

Consider using streamed attachments if the messages you are trying to pass are over one Megabyte in size. Messages over 100 Megabytes in size should definitely be passed as streamed 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.

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.

Assembling Streaming Attachments into a Web Service

This section describes how to assemble a Web Service that uses streaming attachments.

Assembling a Web Service that Supports Streaming Attachments Bottom Up

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.

  1. 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.

  2. Write the implementation of the service.

    "Implementing a Service Interface that Uses Streaming Attachments" provides more information on this step.

  3. 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.

  4. Generate the service artifacts by running the WebServicesAssembler with the assemble command.

  5. Deploy the service and bind the application.

  6. Generate the client-side code.

  7. Compile and run the client.

Writing an Interface for Steaming Attachments

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.

Implementing a Service Interface that Uses Streaming Attachments

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");
        }
    }
}
WSDL Elements for a Service with Streaming Attachments

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>
Writing Stub Code to Handle Streaming Attachments

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 Top Down

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.

  1. Provide a WSDL from which the Web service will be generated.

  2. 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.

  3. Use the WSDL as input to the WebServicesAssembler genInterface command.

  4. Compile the generated interface and type classes.

  5. Write the Java Service Endpoint interface for the Web service you want to provide.

  6. Compile the Java Service Endpoint interface.

  7. Generate the service by running the WebServicesAssembler tool with the topDownAssemble command.

  8. Deploy the service.

  9. Generate the client code.

WSDL Extensions for Streaming Attachments

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>

Understanding the Streaming Attachments API

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

Attachments interface

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.

IncomingAttachments interface

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.

OutgoingAttachments interface

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.

Attachment interface

The Attachment object consists of a String ID to identify the attachment and a data handler to retrieve the data. See "Interface for Attachment Objects" for more information.

AttachmentFactory class

This factory class creates instances of Attachments and Attachment objects. See "Factory Class for Attachment Objects" for more information.


Interface for Attachments

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();
}

Interface for Incoming Attachments

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;
}

Interface for Outgoing Attachments

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);
}

Interface for Attachment Objects

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();
}

Factory Class for Attachment Objects

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();
} 

Working with DIME Attachments

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.

Creating Interoperable DIME-Encoded Messages

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 true.

layout="uri"

Specifies how the primary SOAP message references the attachments in a DIME message. The following are the possible values for the URI.

  • http://schemas.xmlsoap.org/ws/2002/04/dime/closed-layout—Specifies that the primary SOAP message references all parts of a DIME message in the proper order.

  • http://schemas.xmlsoap.org/ws/2002/04/dime/open-layout—Specifies that the DIME message can include additional attachments, even though they are not referenced by the SOAP message. These additional attachments must follow all of the attachments in the DIME message that are referenced by the SOAP message.


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>

Implementing Oracle-Proprietary DIME Encoding

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.

Working with Attachments in WSIF

For information on enabling WSIF clients to handle message attachments, see "Adding Message Attachments in WSIF".

Limitations

See "Working with Message Attachments".

Additional Information

For more information on: