CS639 JAXB Annotations in orderService

In orderService, we see both Order.java and OrderRepresentation.java: what’s the difference?

·         Order.java is the POJO for use inside the application, not to generate XML that goes out.

·         OrderRepresentation is the POJO that drives the external representation in XML. It has the JAXB annotations.

OrderRepresentation.java in orderService:  every child element is annotated, and XMLRootElement is there for JAXB to use this class for deserialization  of an  <order> with the right namespace. Also, item and location are marked as “required = true”, in an attempt to specify proper behavior, but JAXB without validation pays no attention to this requirement, or the order of the child elements.  It would be enforced if we turned on validation.

=======================================================================================================  
package com.restbucks.ordering.representations;

@XmlRootElement(name = "order", namespace = Representation.RESTBUCKS_NAMESPACE)

// Make sure the schema type is in the same namespace, to allow a simple schema

@XmlType(name = "orderRepresentation", namespace = Representation.RESTBUCKS_NAMESPACE)

// FIELD access is better in general for us, so override default PUBLIC_MEMBER

// (but when we put @XmlElement on each field, it doesn’t actually matter)

@XmlAccessorType(XmlAccessType.FIELD)

 

public class OrderRepresentation {

  

    @XmlElement(name = "id", namespace = Representation.RESTBUCKS_NAMESPACE)

    private String id;    

    @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() {}

...

But the above approach is not the only way to make all these elements show up in the XML, in this namespace.  In package domain we have a file package-info.java to contain package annotations to set defaults for the whole package. Note that OrderRepresentation is not in package domain, so it is not helped by this setup, and has no package-info.java in its own package. Because of having no package defaults in place, we need to specify the namespace over and over for OrderRepresentation, as you see above.  Clearly the package defaults are the easy way to go, especially when you’re using namespaces.  File: package-info.java in package com.restbucks.ordering.domain

=======================================================================================================  

@javax.xml.bind.annotation.XmlSchema(namespace = "http://schemas.restbucks.com", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.restbucks.ordering.domain;

=======================================================================================================  

The package annotation namespace = ... marks the whole package as being in this namespace, unless overridden by annotations at the class level (which we don’t need here.) The elementFormDefault = “QUALIFIED” allows each element to default to the NS of its containing element. With these in place for the package, the source for the POJOs in domain is much neater, or could be much neater.  See Javadoc for this annotation in the usual JDK API by selecting the package first.

 

The following is the Item POJO in domain:  It could be simplified by removing the @XmlElement annotations, as long as we don’t mind losing “required” if validated. Without @XmlElement, the namespace for milk, etc., would follow Item’s, which follows the package default set up in package-info. The @XmlRootElement class annotation explains why <item> is a global element in the schema, since @XmlRootElement requires <item> to usable as a root element in XML.

 

=======================================================================================================  

package com.restbucks.ordering.domain;

import ...

// This POJO is marked up for XML, but also used as a "domain object"

// that is, used in server-side implementation code

// That's OK if we aren't leaking any proprietary information

// out, i.e., if the object is so plain that it doesn't matter

// if the outside world sees its structure, and we don't think

// we'll ever change it.

// Note that the Order domain objects *are* separate from

// the OrderRepresentation objects that correspond to the XML

// XmlRootElement is not needed because we never have JAXB

// parse XML with item at the root

@XmlRootElement

public class Item {

    @XmlElement(required = true, namespace = Representation.RESTBUCKS_NAMESPACE)

    private Milk milk;

    @XmlElement(required = true, namespace = Representation.RESTBUCKS_NAMESPACE)

    private Size size;

    @XmlElement(required = true, namespace = Representation.RESTBUCKS_NAMESPACE)

    private Drink drink;

   

    /**

     * For JAXB :-(

     */

    Item(){}

   ...

 

======================================================================================================= 

Sample enum from the domain package: no JAXB annotations needed

=======================================================================================================  

package com.restbucks.ordering.domain;

 

public enum Size {

    SMALL,

    MEDIUM,

    LARGE,

    HUGE

}