CS639 Practice Final Exam
Open books, handouts, solutions, etc.
Show all work on these pages, using backs of pages if needed. Total points = 150. Note that OrderService.xsd, Link.xsd, and OrderRepresentaton.java are included at the end of the exam.
1. Designing XML and Web Services
Cats and dogs have identification collars (or even embedded chips) that give them a unique String id. Suppose you want to set up a registry of these ids so that lost pets can be returned to their owners. You decide to keep, for each registered pet, its unique id, its name (string), its owner’s name (one string, for simplicity), and contact information for the owner consisting of one or more email addresses (strings). You want to provide web services to register a pet, change contact information, and find information on a pet registration given the unique id. Note that in this case the server does not assign the unique id, but just uses it.
b. Give a table summarizing the service contract
overview, like Table 4-1 on pg. 57 of “REST in Practice”. It should have 3
rows, for register pet, change info, and find information on pet, and 3
columns, for Verb, URI or template, and Use.
2. Suppose you are enhancing the system of pa3 to add a (single) password for access to the “poke” action. Since we haven’t studied proper authorization protocols (described in Chap. 9 of the REST book), you have to supply this password in the body of an appropriate message to do the job. Assume a single permanent password in use at the site, stored in a file, read at startup, and held in a private static variable in OrderRepository.
3. Namespaces and XML Schemas
Here is an XML file from a SOAP web services setup (but you don’t need to know SOAP web services for this problem, just XML Schemas):
<deployment name="test"
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service
name="MessageService" provider="java:MSG"
use="literal">
<parameter name="className"
value="samples.message.MessageService" />
<parameter name="allowedMethods" value="echoElements"
/>
</service>
<service
name="MessageService2"
provider="java:MSG" use="literal">
<parameter name="className"
value="samples.message.MessageService" />
<parameter name="allowedMethods" value="process"
/>
</service>
</deployment>
<?xml
version="1.0"?>
<xs:schema elementFormDefault="qualified"
version="1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
targetNamespace=" "
xmlns:tns=" " >
(30) 4. XML Data Binding using JAXB. The schema for element type order is
shown in the attached schema. The corresponding OrderRepresentation object,
with other objects associated with it, is used heavily in orderService. Its
source code is attached at the end of the exam.
Given
the XML:
<?xml version="1.0"
encoding="UTF-8"?>
<order xmlns="http://schemas.restbucks.com">
<id>41</id>
<item>
<milk>SEMI</milk>
<size>LARGE</size>
<drink>CAPPUCCINO</drink>
</item>
<location>TAKEAWAY</location>
<cost>2</cost>
<status>UNPAID</status>
</order>
a. Draw a picture of the corresponding POJO object graph,
that is, one OrderRepresentation object and other objects (including enum
objects) hanging off of it. Use an oval
for each Java object involved, and show ref linkages by arrows. Indicate class names on each Java object,
including objects such as List or Set (objects of some concrete classes for
these are in actual use, of course) from the JDK.
b. Note that OrderRepresentation has no getter for the
List of Items. Explain how the server code gets access to this important data.
Specifically, given an instance of OrderRepresentation orderRep, show code that
counts the number of items.
<?xml version="1.0"
encoding="UTF-8" standalone="yes"?>
<xs:schema elementFormDefault="qualified"
version="1.0" targetNamespace="http://schemas.restbucks.com"
xmlns:tns="http://schemas.restbucks.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="item"
type="tns:item"/>
<xs:element name="order"
type="tns:orderRepresentation"/>
<xs:complexType name="orderRepresentation">
<xs:sequence>
<xs:element name="id"
type="xs:string" minOccurs="0"/>
<xs:element ref="tns:item"
maxOccurs="unbounded"/>
<xs:element name="location"
type="tns:location"/>
<xs:element name="cost"
type="xs:decimal" minOccurs="0"/>
<xs:element name="status"
type="tns:orderStatus" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="item">
<xs:sequence>
<xs:element name="milk"
type="tns:milk"/>
<xs:element name="size"
type="tns:size"/>
<xs:element name="drink"
type="tns:drink"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="milk">
<xs:restriction base="xs:string">
<xs:enumeration value="NONE"/>
<xs:enumeration value="SKIM"/>
<xs:enumeration value="SEMI"/>
<xs:enumeration value="WHOLE"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="size">
<xs:restriction base="xs:string">
<xs:enumeration value="LARGE"/>
<xs:enumeration value="SMALL"/>
<xs:enumeration value="MEDIUM"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="drink">
<xs:restriction base="xs:string">
<xs:enumeration value="FLAT_WHITE"/>
<xs:enumeration value="LATTE"/>
<xs:enumeration value="CAPPUCCINO"/>
<xs:enumeration value="ESPRESSO"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="location">
<xs:restriction base="xs:string">
<xs:enumeration value="IN_STORE"/>
<xs:enumeration value="TAKEAWAY"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="orderStatus">
<xs:restriction base="xs:string">
<xs:enumeration value="PREPARING"/>
<xs:enumeration value="READY"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
---------------------------------------------------------------------------------
<?xml version="1.0"
standalone="yes"?>
<xs:schema version="1.0"
targetNamespace="http://schemas.restbucks.com/dap" xmlns:tns="http://schemas.restbucks.com/dap" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="link"
type="tns:link"/>
<xs:complexType name="link">
<xs:sequence/>
<xs:attribute name="rel"
type="xs:string"/>
<xs:attribute name="uri"
type="xs:string"/>
<xs:attribute name="mediaType"
type="xs:string"/>
</xs:complexType>
</xs:schema>
---------------------------------------------------------------------------------
package com.restbucks.ordering.representations;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import
com.restbucks.ordering.activities.InvalidOrderException;
import com.restbucks.ordering.domain.Item;
import com.restbucks.ordering.domain.Location;
import com.restbucks.ordering.domain.Order;
import com.restbucks.ordering.domain.OrderStatus;
// This annotation is needed, to define the root
element's name and namespace
// not otherwise specified here
@XmlRootElement(name = "order", namespace
= Representation.RESTBUCKS_NAMESPACE)
// Make sure the schema type is in the same
namespace
@XmlType(name = "orderRepresentation",
namespace = Representation.RESTBUCKS_NAMESPACE)
// Better in general for us: default of
.PUBLIC_MEMBER requires a public getter/setter *pair*
// to ensure inclusion of that property in the XML
without an @XmlElement.
// Here cost has a getter but no setter, for example
@XmlAccessorType(XmlAccessType.FIELD)
public class OrderRepresentation {
@XmlElement(name
= "id", namespace = Representation.RESTBUCKS_NAMESPACE)
private
String id;
public
String getId() {
return
id;
}
// we want
to override the default here with required = true, but we could let the
namespace
// be
defaulted to parent's NS
@XmlElement(name
= "item", required = true, namespace =
Representation.RESTBUCKS_NAMESPACE)
private
List<Item> items;
@XmlElement(name = "location", required = true, namespace =
Representation.RESTBUCKS_NAMESPACE)
private
Location location;
@XmlElement(name = "cost", namespace =
Representation.RESTBUCKS_NAMESPACE)
private
BigDecimal cost;
@XmlElement(name
= "status", namespace = Representation.RESTBUCKS_NAMESPACE)
private
OrderStatus status;
/**
* For
JAXB :-(
*/
OrderRepresentation() {}
// for use with OrderResource's commented-out
createOrder version
public
static OrderRepresentation fromXmlString(String xmlRepresentation) {
try {
JAXBContext context =
JAXBContext.newInstance(OrderRepresentation.class);
Unmarshaller unmarshaller =
context.createUnmarshaller();
return (OrderRepresentation) unmarshaller.unmarshal(new
ByteArrayInputStream(xmlRepresentation.getBytes()));
}
catch (Exception e) {
throw
new InvalidOrderException(e);
}
}
public
OrderRepresentation(Order order, String id) {
try {
this.location = order.getLocation();
this.items = order.getItems();
this.cost = order.calculateCost();
this.status = order.getStatus();
this.id = id;
}
catch (Exception ex) {
throw new InvalidOrderException(ex);
}
}
// for
debugging and testing: look at object as XML
public
String toString() {
try {
JAXBContext context =
JAXBContext.newInstance(OrderRepresentation.class);
Marshaller marshaller = context.createMarshaller();
StringWriter stringWriter = new StringWriter();
marshaller.marshal(this, stringWriter);
return stringWriter.toString();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
// For use
only inside server: create an Order from this OrderRepresentation
// The
Order object belongs to the server implementation
//
Luckily, a POJO built from the XML will not have this
// method.
public
Order getOrder() {
if
(location == null || items == null) {
throw new InvalidOrderException();
}
for
(Item i : items) {
if
(i == null) {
throw new InvalidOrderException();
}
}
return
new Order(location, status, items);
}
public
OrderStatus getStatus() {
return
status;
}
public
BigDecimal getCost() {
return
cost;
}
}