B2B with XML

Third-Party Hotel System Uses Email, AQ, and XML

August 2000
Oracle8i

Contents

The TPHS coordinates with the HRS application to update information and keep track of bookings for international hotels (also called third-party hotels). There are 2 modules in the TPHS:

  • TPHotelSystem, implemented as a Java application, listens to the HRS via Advanced Queueing (AQ). When it receives an XML document containing booking information, this application parses it and updates the local schema.
  • TPHSServlet provides an interface for the administrator at the TPHS site. Using this interface, the TPHS admin can add new room types to existing hotels, add new facilities, change room rates, etc. After making the changes, the administrator can notify the HRS via email. When the administrator presses the "Send Mail" button, this servlet fetches the new information from the database and mails it to the HRS in an XML document.

About Messages and Queues

Messages are discrete pieces of information (data) exchanged by applications. Typically, messages consist of two parts:

  • Payload is the gist of the message, the actual information communicated. It could be unstructured information, structured data (relational tables), or self-describing data (such as XML).
  • Control Information defines attributes such as the destination, expiration time, priority, and recipients.

Oracle Advanced Queuing messages have a third part, a history, associated with them. Every message carries its history with it: the nodes it has visited and the recipients that have received it.

Message management involves tracking messages through their entire life-cycle, determining the state and location of messages at any given time, tracking the relationship between messages, and exception management. Applications interact using message queuing as follows:

  1. They create a message and hand it off to the message queuing system.
  2. The message queuing system guarantees the delivery of the message to its destination.
  3. If the destination is temporarily unavailable for any reason (machine, network, or application failure), the message queuing system stores the message persistently and later forwards it to the destination.

Oracle Advanced Queuing is implemented as an integral part of the Oracle database management system. Advanced Queues are relational database tables, enhanced to support queuing operations like enqueue and dequeue. Advanced Queues can store either unstructured (raw) messages or structured (Oracle Objects? ) messages. Messages are stored as rows in a table, and you can use standard SQL to:

  • Access the payload, control information, and history.
  • Optimize access using technology such as indexes.

The figure below shows two queues: Queue Table #1 contains three messages (rows), Queue Table #2 contains four. Each row has columns for message payload, control information, and history.

 

Processing Messages

The following code from xmla2a.tphs.startListening listens for messages. When it gets a request, it parses the message using the Oracle XML Parser for Java, then makes or cancels reservations accordingly (this example shows the details for a cancellation).

  public void startListening() {


    System.out.println("TPHotelSystem Started Listening on the queue...");
    String l_status = "START";
    try {
           ...
      while(!l_status.equals("FINISH")) {

       // Class xmla2a.utilities.AQHandler imports oracle.AQ.*.
       // AQHandler m_handler = null;
      	String l_xmlString = m_handler.dequeueMessage(m_handler.m_reqQueue);
      	ByteArrayInputStream l_bstream =
                             new ByteArrayInputStream(l_xmlString.getBytes());

        // Create an XML document from the given string.
        DOMParser l_parse = new DOMParser();

        l_parse.setPreserveWhitespace(false);
        l_parse.setValidationMode(true);
        l_parse.parse(l_bstream);

        XMLDocument l_doc = l_parse.getDocument();
        NodeList l_bookings=l_doc.getElementsByTagName("Booking");

        // Process all bookings in the XML document.
        for( int i=0; i< l_bookings.getLength(); i++){
          NodeList l_booking = l_bookings.item(i).getChildNodes();
          NodeList l_bookingType = l_booking.item(1).getChildNodes();

          // Find out the request type (Reservation or Cancellation)
          String l_requestType = l_bookingType.item(0).getNodeValue();
          if(l_requestType.equalsIgnoreCase("RESERVATION")){

             ...
          }
          else if(l_requestType.equalsIgnoreCase("CANCELLATION")) {
            l_hotelID =
              Integer.parseInt(l_booking.item(0).getChildNodes().item(0).getNodeValue());
            String l_bookingNote  = l_booking.item(7).getChildNodes().item(0).getNodeValue();
            cancelRooms(l_hotelID, l_bookingNote); 
          }
        }
        l_bstream.close();    // Close the byte array stream
      }
    } catch(Exception ex) {  // Trap the Errors
       System.out.println("Error is "+ ex.toString());
       l_status="FINISH";
    }
  }

The class xmla2a.utilities.AQHandler imports oracle.AQ.* to provide some queue-processing methods, and implements methods such as dequeueMessage (shown below).

  public String dequeueMessage(AQQueue p_queue) {
AQMessage l_message=null;
AQRawPayload l_rawPayload;
AQDequeueOption l_deqOption;
byte[] l_array;
try {
// Create a AQDequeueOption object with default options:
l_deqOption = new AQDequeueOption();
l_deqOption.setCorrelation("5810");
// Dequeue a message:
l_message = p_queue.dequeue(l_deqOption);
// Retrieve raw data from the message:
l_rawPayload = l_message.getRawPayload();
l_array = l_rawPayload.getBytes();
return new String(l_array);
} catch(Exception e) { // Catch the exception
System.out.println("Exception :"+ e.toString());
return "Fail";
}
}

Handling Messages with a Servlet

In contrast to the TPHotelSystem, a Java application that uses Advanced Queueing to listen for and process messages from other modules, the TPHSServlet implements a service method (as all servlets must, according to the servlet spec) to do much the same thing. The following code from xmla2a.tphs.TPHSServlet.service shows the flow of execution when the TPHS admin changes the availability of a hotel room.

  public void service(HttpServletRequest p_request,
HttpServletResponse p_response)
throws ServletException, IOException { // Set parameters for the servlet response.
p_response.setHeader("pragma","no-cache");
p_response.setContentType("text/html"); String l_reqType = p_request.getParameter("REQ_TYPE");
String l_hotelID = p_request.getParameter("HOTEL_ID"); if (l_reqType == null){ ... } else if (l_reqType.equals("CHANGE_AVAILABILITY")){
PrintWriter l_write = p_response.getWriter();
p_response.setContentType("text/html");
try{
m_data = this.fetchAvailability(l_hotelID); // Build HTML form for entering new availability data.
TPHSServletHTML.putChangeAvailPage(l_write, m_data, l_hotelID);
l_write.close();
} catch(Exception ex){
l_write.println(TPHSServletHTML.showErrorPage(ex.toString()));
} } else if (l_reqType.equals("COMMIT_CHANGED_AVAIL")){
PrintWriter l_write = p_response.getWriter();
p_response.setContentType("text/html"); try {
m_updatedData = m_updatedData || this.commitChangedAvail(p_request); // Build HTML page to display status message.
TPHSServletHTML.genMessagePage(l_write, m_message," ");
l_write.close();
} catch(Exception ex){
l_write.println(TPHSServletHTML.showErrorPage(ex.toString()));
} ... } else if (l_reqType.equals("SEND_MAIL")) {
PrintWriter l_write = new PrintWriter(p_response.getOutputStream());
if(m_updatedData){
m_updatedData = false;
this.sendUpdatesMailToHRS();
TPHSServletHTML.genMessagePage(l_write,m_message,"Show RAW XML data");
} else {
m_message="Mail can be sent only when you have updated "+
"hotel information.";
TPHSServletHTML.genMessagePage(l_write, m_message," ");
}
l_write.close(); // close the writer object
}

The following code from xmla2a.tphs.TPHSServlet.sendUpdatesMailToHRS shows how the TPHS sends email to the HRS. It creates an empty XML document, writes an XML document to the message body, then calls xmla2a.utilities.MailHandler.sendMail to mail the message.

public void sendUpdatesMailToHRS(){
  // close Updates XML doc
  m_updatesMailDoc.endElement(m_mailRoot); 
  l_mailBody = m_updatesMailDoc.getXMLDocumentString();


  // Create an empty document.

  m_updatesMailDoc = createXMLRoot();
  // Send updates to the HRS via email.

  // MailHandler m_mailHandler
  m_mailHandler.sendMail(MailParams.s_hrsMailID,
                         MailParams.s_mailServerName,
                         l_mailBody);
  m_message = "Message sent to HRS Successfully.";
}

The following code from xmla2a.utilities.MailHandler.sendMail uses the Internet mail protocol SMTP to send email. It imports key functionality from javax.mail.* and javax.mail.internet.*.

  public void sendMail(String p_userName, 
                       String p_hostName,
                       String p_messageBody){
try{
java.util.Properties l_props = System.getProperties();
l_props.put("mail.smtp.host", p_hostName);
Session l_session = Session.getDefaultInstance(l_props, null);

MimeMessage l_message = new MimeMessage(l_session);
l_message.setSubject("TPHS XML Updates");
l_message.setText(p_messageBody);
l_message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(p_userName));

Transport.send(l_message);
} catch (MessagingException ex){
ex.printStackTrace();
}
}

< Back to Introduction


Questions or comments? Post a message in OTN's Sample Code discussion forum or send email to the author.

B2B with XML: Third-Party Hotel System
Author: Robert Hall, Oracle Corporation
Date: August 2000

This document is provided for information purposes only and the information herein is subject to change without notice. Please report any errors herein to Oracle Corporation. Oracle Corporation does not provide any warranties covering and specifically disclaims any liability in connection with this document.

Oracle is a registered trademark and Enabling the Information Age is a trademark or registered trademark of Oracle Corporation. All other company and product names mentioned are used for identification purposes only and may be trademarks of their respective owners.

Oracle Corporation
World Headquarters
500 Oracle Parkway
Redwood Shores, CA 94065
U.S.A.

Worldwide Inquiries:
+1.650.506.7200
Copyright © Oracle Corporation 2000
All Rights Reserved


E-mail this page
Printer View Printer View
Oracle Is The Information Company About Oracle | Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy