B2B with XML
Third-Party Hotel System Uses Email, AQ, and XML
August 2000 |
 |
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:
- They create a message and hand it off to the message queuing system.
- The message queuing system guarantees the delivery of the message to its
destination.
- 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(); } }
|
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
|