The Java EE 5 Tutorial

Ordering Coffee

The other kind of message that the Coffee Break servers can send to the SAAJ supplier is an order for coffee. This is done in the placeOrder method of OrderRequest, which follows the DTD coffee-order.dtd.

Creating the Order

As with the client code for requesting a price list, the placeOrder method starts by creating a SOAPConnection object and a SOAPMessage object and accessing the message’s SOAPBody object.

SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
SOAPConnection con = scf.createConnection();

MessageFactory mf = MessageFactory.newInstance();
SOAPMessage msg = mf.createMessage();

SOAPBody body = msg.getSOAPBody();

Next, the code creates and adds XML elements to form the order. As is required, the first element is a SOAPBodyElement, which in this case is coffee-order.

QName bodyName = new QName("http://sonata.coffeebreak.com",
    "coffee-order", "PO");
SOAPBodyElement order = body.addBodyElement(bodyName);

The application then adds the next level of elements, the first of these being orderID. The value given to orderID is extracted from the OrderBean object passed to the OrderRequest.placeOrder method.

QName orderIDName = new QName("orderID");
SOAPElement orderID = order.addChildElement(orderIDName);
orderID.addTextNode(orderBean.getId());

The next element, customer, has several child elements that give information about the customer. This information is also extracted from the Customer component of OrderBean.

QName childName = new QName("customer");
SOAPElement customer = order.addChildElement(childName);

childName = new QName("last-name");
SOAPElement lastName = customer.addChildElement(childName);
lastName.addTextNode(orderBean.getCustomer().getLastName());

childName = new QName("first-name");
SOAPElement firstName = customer.addChildElement(childName);
firstName.addTextNode(orderBean.getCustomer().getFirstName());

childName = new QName("phone-number");
SOAPElement phoneNumber = customer.addChildElement(childName);
phoneNumber.addTextNode(orderBean.getCustomer().getPhoneNumber());

childName = new QName("email-address");
SOAPElement emailAddress = customer.addChildElement(childName);
emailAddress.addTextNode(orderBean.getCustomer().getEmailAddress());

The address element, added next, has child elements for the street, city, state, and zip code. This information is extracted from the Address component of OrderBean.

childName = new QName("address");
SOAPElement address = order.addChildElement(childName);

childName = new QName("street");
SOAPElement street = address.addChildElement(childName);
street.addTextNode(orderBean.getAddress().getStreet());

childName = new QName("city");
SOAPElement city = address.addChildElement(childName);
city.addTextNode(orderBean.getAddress().getCity());

childName = new QName("state");
SOAPElement state = address.addChildElement(childName);
state.addTextNode(orderBean.getAddress().getState());

childName = new QName("zip");
SOAPElement zip = address.addChildElement(childName);
zip.addTextNode(orderBean.getAddress().getZip());

The element line-item has three child elements: coffeeName, pounds, and price. This information is extracted from the LineItems list contained in OrderBean.

List<LineItemBean> lineItems = orderBean.getLineItems();
Iterator<LineItemBean> i = lineItems.iterator();
while (i.hasNext()) {
    LineItemBean lib = i.next();

    childName = new QName("line-item");
    SOAPElement lineItem = order.addChildElement(childName);

    childName = new QName("coffeeName");
    SOAPElement coffeeName = lineItem.addChildElement(childName);
    coffeeName.addTextNode(lib.getCoffeeName());

    childName = new QName("pounds");
    SOAPElement pounds = lineItem.addChildElement(childName);
    pounds.addTextNode(lib.getPounds().toString());

    childName = new QName("price");
    SOAPElement price = lineItem.addChildElement(childName);
    price.addTextNode(lib.getPrice().toString());
}

// total
childName = new QName("total");
SOAPElement total = order.addChildElement(childName);
total.addTextNode(orderBean.getTotal().toString());

With the order complete, the application sends the message to the endpoint http://localhost:8080/saaj-coffee-supplier/orderCoffee and closes the connection.

URL endpoint = new URL(url);
SOAPMessage reply = con.call(msg, endpoint);
con.close();

Because the given endpoint is mapped to ConfirmationServlet, the Application Server executes that servlet (discussed in Returning the Order Confirmation) to create and return the SOAPMessage object reply.

Retrieving the Order Confirmation

The rest of the placeOrder method retrieves the information returned in reply. The client knows what elements are in it because they are specified in confirm.dtd. After accessing the SOAPBody object, the code retrieves the confirmation element and gets the text of the orderID and ship-date elements. Finally, it constructs and returns a ConfirmationBean with this information.

SOAPBody sBody = reply.getSOAPBody();
Iterator bodyIt = sBody.getChildElements();
SOAPBodyElement sbEl = (SOAPBodyElement)bodyIt.next();
Iterator bodyIt2 = sbEl.getChildElements();

SOAPElement ID = (SOAPElement)bodyIt2.next();
String id = ID.getValue();

SOAPElement sDate = (SOAPElement)bodyIt2.next();
String shippingDate = sDate.getValue();

SimpleDateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
Date date = df.parse(shippingDate);
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
cb = new ConfirmationBean();
cb.setOrderId(id);
cb.setShippingDate(DatatypeFactory.newInstance().newXMLGregorianCalendar(cal));