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;
}
}