Skip Headers
Oracle® XML Developer's Kit Programmer's Guide
10g Release 2 (10.1.2)
Part No. B14033-01
  Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

11 Using XDK and SOAP

This chapter contains these topics:

What Is SOAP?

The term Web Services is used to describe a functionality made available by an entity over the Web. It is an application that uses XML standards and is published, located and executed through the Web.

The Simple Object Access Protocol (SOAP) is a lightweight protocol for sending and receiving requests and responses across the Internet. Because it is based on XML and simple transport protocols such as HTTP, it is not blocked by firewalls and is very easy to use. SOAP is independent of operating system, implementation language, and any single object model.

SOAP supports remote procedure calls. Its messages are only of the three types:

SOAP messages consist of:

SOAP 1.1 specification is a World Wide Web Consortium (W3C) note. The W3C XML Protocol Working Group has been formed to create a standard that will supersede SOAP 1.1. Oracle is a member of this group. The standard will be called SOAP 1.2.

A SOAP service remote procedure call (RPC) request and response sequence includes the steps:

  1. A SOAP client writes a request for service in a conforming XML document, using either an editor or the Oracle SOAP client API.

  2. The client sends the document to a SOAP Request Handler running as a servlet on a Web server.

  3. The Web Server dispatches the message as a service request to an appropriate server-side application providing the requested service.

  4. The application must verify that the message contains supported parts. The response from the service is returned to the SOAP Request Handler servlet and then to the caller using the SOAP payload format.

What Are UDDI and WSDL?

The Universal Description, Discovery and Integration (UDDI) specification provides a platform-independent framework using XML to describe services, discover businesses, and integrate business services on the Internet. The UDDI business registry is the public database where companies are registered. The UDDI business registration is an XML file with three sections:

The Web Services Description Language (WSDL) is a general purpose XML language for describing the interface, protocol bindings, and deployment details of Web Services. WSDL provides a method of describing the abstract interface and arbitrary network services. A WSDL service is registered or embedded in the UDDI registry.

The stack of protocol stack used in Web Services is summarized in the following list:

What Is Oracle SOAP?

Oracle SOAP is an implementation of the Simple Object Access Protocol. Oracle SOAP is based on the SOAP open source implementation developed by the Apache Software Foundation.

How Does Oracle SOAP Work?

Consider this example: a GetLastTradePrice SOAP request is sent to a StockQuote service. The request takes a string parameter, the company stock symbol, and returns a float in the SOAP response. The XML document represents the SOAP message. The SOAP envelope element is the top element of the XML document. XML namespaces are used to clarify SOAP identifiers from application-specific identifiers. The following example uses HTTP as the transport protocol. The rules governing XML payload format in SOAP are independent of the fact that the payload is carried in HTTP. The SOAP request message embedded in the HTTP request is:

POST /StockQuote HTTP/1.1
Host: www.stockquoteserver.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "Some-URI"
<SOAP-ENV:Envelope  xmlns:SOAP-   ENV="http://schemas.xmlsoap.org/soap/
envelope/"  SOAP-
ENV:encodingStyle="http://schemas.xnlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<m:GetLastTradePrice xmlns:m="Some-URI">
<symbol>ORCL</symbol>
<m:GetLastTradePrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Here is the response HTTP message:

HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn

<SOAP-ENV:Envelope  xmlns:SOAP- 
ENV=http://schemas.xmlsoap.org/soap//envelope/ SOAP-
ENV:encodingStyle="http://schemas.xnlsoap.org/soap/encoding/"/>
<SOAP-ENV:Body>
<m:GetLastTradePriceResponse xmlns:m="Some-URI">
<Price>34.5</Price>
</m:GetLastTradePriceResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Oracle SOAP and IDAP

IDAP is an XML-based specification to perform AQ operations. SOAP defines a generic mechanism to invoke a service. IDAP defines these mechanisms to perform AQ operations.

IDAP has the following key properties not defined by SOAP:

  • Transactional behavior - You can perform AQ operations in a transactional manner. Your transaction can span multiple IDAP requests.

  • Security - All the IDAP operations can be done only by authorized and authenticated users.

  • You can also perform AQ operations through the SOAP interface. AQ encapsulates operations in IDAP format.

  • Character set transformations - This is a very important requirement for any communication. Internet user's machine may have different character set id than the server machine.

  • Extensible AQ Servlet for AQ Internet operations - The AQ servlet performing AQ operations is extensible. You can specify time-out, connection pooling, TAF, apply XML stylesheets, perform post AQ and pre-AQ database operations in the AQ Servlet.

There is no difference in SOAP and IDAP access to AQ except the line specifying the namespace for the envelope.

For IDAP that line is:

<Envelope xmlns="http://ns.oracle.com/AQ/schemas/envelope">

While in SOAP, it is:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">

Everything else remains the same.

What Is a SOAP Client?

A SOAP client application represents a user-written application that makes SOAP requests. The SOAP client has these capabilities:

  • Gathers all parameters that are needed to invoke a service.

  • Creates a SOAP service request message. This is an XML message that is built according to the SOAP protocol and that contains all the values of all input parameters encoded in XML. This process is called serialization.

  • Submits the request to a SOAP server using some transport protocol that is supported by the SOAP server.

  • Receives a SOAP response message.

  • Determines the success or failure of the request by handling the SOAP Fault element.

  • Converts the returned parameter from XML to native datatype. This process is called deserialization.

  • Uses the result as needed.

SOAP Client API

SOAP clients generate the XML documents that compose a request for a SOAP service and handle the SOAP response. Oracle SOAP processes requests from any client that sends a valid SOAP request. To facilitate client development, Oracle SOAP includes a SOAP client API that provides a generic way to invoke a SOAP service.

The SOAP client API supports a synchronous invocation model for requests and responses. The SOAP client API makes it easier for you to write a Java client application to make a SOAP request. The SOAP client API encapsulates the creation of the SOAP request and the details of sending the request over the underlying transport protocol. The SOAP client API also supports a pluggable transport, allowing the client to easily change the transport (available transports include HTTP and HTTPS).

What Is a SOAP Server?

A SOAP server has the following capabilities:

  • The server receives the service request.

  • The server parses the XML request and then decides to execute the message or reject it.

  • If the message is executed, the server determines if the requested service exists.

  • The server converts all input parameters from XML into datatypes that the service understands.

  • The server invokes the service.

  • The return parameter is converted to XML and a SOAP response message is generated.

  • The response message is sent back to the caller.

Oracle SOAP Security Features

Oracle SOAP uses the security capabilities in the transport to support secure access and to support other security features. For example, using HTTPS, Oracle SOAP provides confidentiality, authentication, and integrity over the Secure Sockets Layer (SSL). Other security features such as logging and authorization are provided by the service provider.

SOAP Transports

SOAP transports are the protocols that carry SOAP messages. Oracle SOAP supports the following transports:

  • HTTP: This protocol is the basic SOAP transport. The Oracle SOAP Request Handler Servlet manages HTTP requests and supplies responses directly over HTTP. This protocol is becoming a standard because of its popularity.

  • HTTPS: The Oracle SOAP Request Handler Servlet manages HTTPS requests and supplies responses, with different security levels supported.

Administrative Clients

SOAP administrative clients include the Service Manager and the Provider Manager. These administrative clients are services that support dynamic deployment of new services and new providers.

SOAP Request Handler

The SOAP Request Handler is a Java servlet that receives SOAP requests, looks up the appropriate service provider, handles the service provider that invokes the requested method (service), and returns the SOAP response, if any.

SOAP Provider Interface and Providers

Oracle SOAP includes a provider implementation for Java classes. Other providers can be added.

Provider Interface

The provider interface allows the SOAP server to uniformly invoke service methods regardless of the type of provider (Java class, stored procedure, or some other provider type). There is one provider interface implementation for each type of service provider, and it encapsulates all provider-specific information. The provider interface makes SOAP implementation easily extensible to support new types of service providers.

Provider Deployment Administration

Oracle SOAP provides the provider deployment administration client to manage provider deployment information.

SOAP Services Provided

SOAP application developers provide SOAP services. These services are made available using the supplied default Java class provider or custom providers. Oracle SOAP includes a service deployment administration client that runs as a service to manage SOAP services. SOAP services, including Java services, represent user-written applications that are provided to remote SOAP clients.

Advantages of XML Over EDI

Here are facts about Electronic Data Interchange (EDI):

  • EDI is a difficult technology: EDI enables machine-to-machine communication in a format that developers cannot easily read and understand.

  • EDI messages are very difficult to debug. XML documents are readable and easier to edit.

  • EDI is not flexible: It is very difficult to add a new trading partner as part of an existing system; each new trading partner requires its own mapping. XML is extremely flexible and has the ability to add new tags on demand and to transform an XML document into another XML document, for example, to map two different formats of purchase order numbers.

  • EDI is expensive: developer training costs are high, and deployment of EDI requires very powerful servers that need a specialized network. EDI runs on Value Added Networks, which are expensive. XML works with inexpensive Web servers over existing Internet connections.


    See Also:

    For more information about Oracle SOAP and Web Services, including documentation and downloads, see:

SOAP Example

Consider an enterprise or government entity that has inventories to be maintained at its headquarters, and at multiple remote branches. The SOAP solution to be described in this chapter considers the headquarters as a message server and the branches as message clients. Among the several tasks to be performed are:

Consider HQ inventory monitoring and the task of informing the branches when a new item is added to the HQ inventory. This example solves this problem with SOAP messaging and several XML features.

The branches can be using non-Oracle databases, because SOAP is not dependent on any DBMS. You can generalize this example so that it can be used for communicating with customers, suppliers, or other entities that are not part of your organization.

XML Features Used in the SOAP Example

The SOAP messages employ the following features:

  • Advanced Queuing (AQ). This Oracle feature uses asynchronous communications between applications and users, with transaction control and security. AQ keeps users from being blocked when they enter new inventory items at HQ.

  • AQ provides the Java Messaging Service (JMS) APIs to enqueue and dequeue the messages.

  • Columns with datatype XMLType are used to store SOAP messages in database tables, so that data about new items will not be lost.

  • XML Compression reduces the payload size and speeds the transmission of messages.

  • XSQL Servlet is used to publish content and for interacting with administrators.

  • The message server at HQ invokes remote procedure calling (RPC).

  • The SOAP call generates an HTTP request, encapsulates the inventory update request in a SOAP message, and invokes the SOAP service on all branches.

  • Each branch either returns a confirmation or returns a fault (defined in the SOAP standard) to the message server.

Prerequisite Software for the SOAP Example

  • Oracle Database

  • XML Developer's Kit (XDK), Java components

  • OC4J

  • The SOAP example, "Build an XML-Powered Distributed Application", can be downloaded from the OTN:


    See Also:

    Download the SOAP example at http://www.oracle.com/technology/tech/xml/

How Is the SOAP Example Implemented?

An overview of the distributed inventory application is shown in the following illustration:

Figure 11-1 Using Soap in a Distributed Inventory Application

Description of adxdk112.gif follows
Description of the illustration adxdk112.gif

SOAP is used to manage inventory at each of the remote branches and at headquarters. The headquarters inventory application is a message server and the branch inventory application is a message client, each using SOAP services.

When headquarters adds a new item to its inventory, it broadcasts a message to all remote client branches that have registered with the message server. A message broker creates a message and pushes it onto the message queue, using AQ. AQ enables asynchronous communications between user applications, providing transaction control, security and preventing blocking of the entry of new items by the users at headquarters.

A message dispatcher process, which is listening to the message queue, detects the enqueued messages and calls the branches' SOAP services to dequeue the message and to update their local inventories.

The messages are stored in the database with complete logging information. The SOAP messages are stored in XMLType datatype instances and are thus a record of sent and received messages. This insures data integrity in the inventories.

At headquarters a table is created initially that has three columns: an identification number, a message of datatype XMLType, and a creation time.

XML Compression is another technology used to lower payloads, making throughput greater in large applications.

Setting Up the Tables and the SOAP Service

To store inventory data, log messages, and perform message queuing, run the createdb.sql script from the downloaded source files to set up database schemas for headquarters and a branch. This script calls a set of SQL scripts that creates a headquarters user and a branch user with proper privileges. It also creates tables and triggers for storing inventory information and messages and inserts sample data in both schemas.

In the headquarters user schema, create a table named message_out_type. This stores the inventory information update broadcast messages from headquarters to the branches. There are three columns in the table: ID, MESSAGE, and CREATE_TIME. The MESSAGE column datatype is XMLType.

Next, run the PL/SQL procedure, CREATE_QUEUE, that sets up message queues at both headquarters and the branches. This procedure uses functions in the DBMS_AQADM package to create the queue table, create the queue, and start the queue. Once the queue is started, enqueuing and dequeuing operations on the message queue are enabled.

The following PL/SQL procedure uses the SYS.AQ$_JMS_BYTES_MESSAGE message type to manage the compressed SOAP messages. This creates a queue called broadcastb_queue at the headquarters location:

begin  
    create_queue('broadcastb_queue_tbl',
    'broadcastb_queue',
    'SYS.AQ$_JMS_BYTES_MESSAGE');
end;

The inventoryBranchServer Java class is the branch's service for inserting a new item into the branch inventory. When this service program receives a SOAP request, it decompresses the request content and saves it in the inventory_item table, using Oracle XML SQL Utility (XSU) to insert the item into the database. Oracle XSU creates canonical mappings between the XML document and database schema to perform SQL data operations. See the file

client/src/oracle/xml/pm/demo/branch/service/inventoryServer.java

in the downloaded software.

Requesting SOAP Service

The application makes requests to the headquarters SOAP service using a servlet called insertItemServlet, a Java class that extends HttpServlet. This servlet inserts a new item in the headquarters inventory.

The servlet request uses XSQL pages and the user's input in the application's Web interface (click "New Items") to generate an XML document. Oracle XSU then directly inserts the XML content into the database. The insertItemServlet performs several actions. For example, to broadcast an update message to the branches, it:

  • Initializes the Message Dispatcher process.

  • Compresses the XML document by calling the CompressionAgent class.

  • Creates a SOAP message and stores it in the message logging table.

  • Pushes the compressed XML document onto the message queue (enqueue).

Initializing the MessageDispatcher Process

When it is first called, insertItemServlet initializes the MessageDispatcher object. This object is stored in the ServletContext when the process is successfully initialized. This code initializes the MessageDispatcher object:

ServletContext context = getServletContext();
MessageDispatcher msgDispatcher =
    (MessageDispatcher)context.getAttribute("Dispatcher");

if (msgDispatcher == null) {
   System.out.println("Initialize Receiver.");
   msgDispatcher = new MesageDispatcher();
   context.setAttribute("Dispatcher",msgDispatcher);
   }

The MessageDispatcher Java class creates a MessageBroker, which in turn, creates a MessageClient to monitor each message queue and dispatch messages to the registered branches.

Compressing the XML Document

The following code from insertItemServlet creates the Compression Agent:

CompressionAgent cagent = new
   CompressionAgent("oracle:compression");
byte [] input = cagent.compression(m_content);

Creating a SOAP Message

The message is stored in a column defined as XMLType. The code from insertItemServlet that creates the SOAP message and stores it in the MESSAGE_OUT_XMLTYPE table is:

OraclePreparedStatement pstmt =
    (OraclePreparedStatement) conn.prepareStatement (
          "Insert into message_out_xmltype(message) values(?)");

m_content=createSOAPMessage(m_content);
oracle.xdb.XMLType xt = oracle.xdb.XMLType.createXML(conn,m_content);

pstmt.setObject(1, xt);
pstmt.execute();

Using XMLType lets us use XPATH with the sys.XMLType.extract() member function to query the portions of the message documents:

select e.message.extract('//item_info')
   .getStringVal() as result
from message_out_xmltype;

Enqueuing the XML Document

The following code from insertItemServlet creates the MessageBroker and enqueues the message:

MessageBroker mesgBroker =
   new MessageBroker("host_name",
   "Oracle_SID", "port_num",
   "thin", "cm", "cm", "broadcastb_queue");
mesgBroker.enqueueMessage(input);

When insertItemServlet finishes, the message is pushed onto the message queue and the Oracle AQ and MessageDispatcher processes update the branch inventory information. This ensures that the headquarters inventory system is not blocked during the branch system updates.

Listing of the Java Source File inserItemServlet.java

This file is found at ./server/src/insertItemServlet.java:

/**
 * FileName: insertItemServlet.java
 * Description: 
 *   Insert new Inventory Item into HQ database and broadcase the message to 
 *   the branches.
 */
import java.io.*;
import java.util.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;

// XSU
import org.w3c.dom.*;
import oracle.xml.parser.v2.*;
import oracle.xml.sql.dml.OracleXMLSave;

// XMLType
import oracle.xdb.XMLType.*;
import oracle.jdbc.driver.*;
import oracle.sql.*;

// SOAP Message
import oracle.AQ.*;
import oracle.xml.pm.queue.*;
import oracle.xml.pm.compression.CompressionAgent;

// Configuration
import oracle.xml.pm.util.ConfigManager;

/**
 * This class implements Message Borker
 */
public class insertItemServlet extends HttpServlet
{
  String m_content=null;
  String m_dblink = null;
  String m_usr = null;
  String m_passwd = null;
  String m_hostname = null;
  String m_sid = null;
  String m_port = null;
  
  /**
   * Initialize global variables
   * @param config - ServletConfig 
   * @exeception - ServletException thrown if super.init fails
   */
  public void init(ServletConfig config) throws ServletException 
  {
    super.init(config);

    // Initialize the JDBC Connection from Configuration Files
    try
    {
      ConfigManager xml_config = new ConfigManager("DEMOConfig.xml","cm");  
      m_dblink = xml_config.dblink;
      m_usr= xml_config.usr;
      m_passwd = xml_config.passwd;
      m_hostname = xml_config.hostname;
      m_sid = xml_config.db_sid;
      m_port = xml_config.db_port;
    }
    catch(Exception ex)
    {
      // ex.printStackTrace();
      throw new ServletException(ex.getMessage());
    }
  }

  /**
   * HTTP Get 
   * @param req - HttpServletRequest
   * @param res - HttpServletResponse 
   * @exeception - IOException, ServletException
   */
   public void doGet(HttpServletRequest req, HttpServletResponse res)
       throws IOException, ServletException
  {
     doPost(req,res);
  }

  /**
   * HTTP POST 
   * @param req - HttpServletRequest
   * @param res - HttpServletResponse 
   * @exeception - IOException, ServletException
   */
  public void doPost(HttpServletRequest req, HttpServletResponse res)
  throws IOException, ServletException
  {
    ServletContext context = getServletContext();

    // Initialize MessageDispatcher for broadcast messages
    MessageDispatcher msgDispatcher =
      (MessageDispatcher) context.getAttribute("MessageDispatcher");
 
    if(msgDispatcher == null)
    {
        msgDispatcher = new MessageDispatcher("broadcastb_queue",m_hostname,
        m_sid, m_port, m_usr,m_passwd,m_dblink);
        context.setAttribute("MessageDispatcher",msgDispatcher);
     }

    // Initialize MessageBroker for broadcasting messages
    MessageBroker msgBroker = (MessageBroker) 
                                  context.getAttribute("MessageBroker");
    if(msgBroker == null)
    {
      try
      {
        msgBroker = new MessageBroker(m_hostname, m_sid, m_port, "thin",m_usr,
                                      m_passwd,"broadcastb_queue",m_dblink);
        context.setAttribute("MessageBroker",msgBroker);
      }
      catch(Exception ex)
      {
        System.out.println("Error:"+ex.getMessage());
      }
    }
    
    PrintWriter out = res.getWriter();
    m_content = req.getParameter("content");

    // Save new Item information into database
    try 
    {
      Connection conn = getConnection();
      
      OracleXMLSave sav = new OracleXMLSave(conn,"inventory_item_view");
      sav.insertXML(m_content);
      sav.close();
      conn.close();
        
      out.println("Insert Successful\n");
    }
    catch(Exception e)
    {
      out.println("Exception caught "+e.getMessage());
      return;
    }

    // Create and Enqueue the Message
    byte[] input = createMessage(m_content);
    msgBroker.enqueueBytesMessage(input); 

    return;
  }

  // Subject to change to validate and using XML Update language
  // Since this message is not public we keep it with simplified SOAP format
  public byte[] createMessage(String content)
  {
     String message = null;

     message="<Envelope>"+
            "<Header>"+
            "<branch_sql>"+"select id,soapurl from branch"+"</branch_sql>"+
            "<objURI>"+"inventoryServer"+"</objURI>"+
            "<method>"+"addItem"+"</method>"+
            "</Header>"+
            "<Body>"+content+"</Body>"+    
            "</Envelope>";
     
    // Compress the Message Content
    CompressionAgent cagent = new CompressionAgent("oracle:xml:compression");
    byte [] input = cagent.compress(message);

    return input;
  }

  /**
   * Get JDBC Connection
   * @return Connection - JDBC Connection 
   * @exception SQLException - thrown if the connection can't be gotten.
   */
  public Connection getConnection() throws SQLException
  {
    DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
    Connection conn =DriverManager.getConnection (m_dblink,m_usr,m_passwd);
    return conn;
  }
}

Queuing Messages with AQ

The MessageBroker class is the agent that communicates with the message queue and invokes SOAP Remote Procedure Call (RPC).

The MessageBroker provides the following functionality:

Message Enqueuing and Dequeuing.

AQ provides standard Java Message Service (JMS) APIs to enqueue and dequeue the messages. Before these operations, however, you need to get a QueueConnection, create a QueueSession with it, and get the message queue. During each QueueSession, QueueSessioncommit() is used for transactional control. If anything goes wrong when our messaging system sends messages to the branches, the commit will not occur and the message will remain in the database.

Invoking Remote SOAP Services.

MessageBroker invokes the remote SOAP service with RPCCall Agent (in the RPCCall Java class). The SOAP RPCCall creates a Call object to specify the SOAP service and adds parameters to the parameters vector for the Call object. The Call object will invoke the remote SOAP service and return "Fault code" if there are errors. We define a Service object in the Service Java class to describe the Service information.

The SOAP call will generate the HTTP request, encapsulate the inventory update request in a SOAP message, and invoke the SOAP service on all branches. When headquarters calls a branch inventory service, the branch sends a confirmation back to it.

XML Compression

To make the messaging system more efficient, use XML compression. This lets you compress or decompress a message by using Java object serialization, such as:

XMLDocument.writeExternal(...);
XMLDocument.readExternal(...);

Our sample application uses the CompressionAgent Java class to provide the compress and decompress functionality. CompressionAgent includes both compress and decompress methods. The compress method returns a byte array and the decompress method returns an XML document.

Listing of the Java Source File MessageBroker.java

This lengthy source file is found at ./xmlagents/src/oracle/xml/pm/queue

Some of the more important functions are sendSOAPMessage(), which sends SOAP files and dequeueTextMessage(), which dequeues information for each inventory item.

Summary of the SOAP Example

Using AQ and XDK in a SOAP messaging system can greatly improve reliability and performance. Inventory update messages are delivered quickly. If they cannot be delivered, they are stored and logged for sending again. These features provide reliable and asynchronous message queuing and speed the transfer of XML message data.