<chapter id="Built_in_JAXB_providers">
   <title>JAXB providers</title>

   <para>

      As required by the specification, RESTEasy JAX-RS includes support for (un)marshalling JAXB annotated classes.
      RESTEasy provides multiple JAXB Providers to address some subtle differences between classes generated by XJC
      and classes which are simply annotated with @XmlRootElement, or working with JAXBElement classes directly.
   </para>
   <para>

      For the most part, developers using the JAX-RS API, the selection of which provider is invoked will be
      completely transparent. For developers wishing to access the providers directly (which most folks won't need to
      do), this document describes which provider is best suited for different configurations.
   </para>
   <para>

      A JAXB Provider is selected by RESTEasy when a parameter or return type is an object that is annotated with
      JAXB annotations (such as @XmlRootEntity or @XmlType) or if the type is a JAXBElement. Additionally, the
      resource class or resource method will be annotated with either a @Consumes or @Produces annotation and
      contain one or more of the following values:
   </para>
   <para>

      <itemizedlist>

         <listitem>
            text/*+xml
         </listitem>

         <listitem>
            application/*+xml
         </listitem>

         <listitem>
            application/*+fastinfoset
         </listitem>

         <listitem>
            application/*+json
         </listitem>

      </itemizedlist>

   </para>
   <para>

   </para>
   <para>

      RESTEasy will select a different provider based on the return type or parameter type used in the resource. This
      section describes how the selection process works.
   </para>
   <para>

      @XmlRootEntity
      When a class is annotated with a @XmlRootElement annotation, RESTEasy will select the
      JAXBXmlRootElementProvider. This provider handles basic marshaling and unmarshalling of custom JAXB
      entities.
   </para>
   <para>

      @XmlType
      Classes which have been generated by XJC will most likely not contain an @XmlRootEntity annotation. In order
      for these classes to marshalled, they must be wrapped within a JAXBElement instance. This is typically
      accomplished by invoking a method on the class which serves as the XmlRegistry and is named ObjectFactory.
   </para>
   <para>

      The JAXBXmlTypeProvider provider is selected when the class is annotated with an XmlType annotation and not an
      XmlRootElement annotation.
   </para>
   <para>

      This provider simplifies this task by attempting to locate the XmlRegistry for the target class. By default, a
      JAXB implementation will create a class called ObjectFactory and is located in the same package as the target
      class. When this class is located, it will contain a &quot;create&quot; method that takes the object instance
      as a parameter. For example, if the target type is called &quot;Contact&quot;, then the ObjectFactory class
      will have a method:
   </para>
   <para>

      public JAXBElement createContact(Contact value) {..
   </para>
   <para>

      JAXBElement&lt;?&gt;
      If your resource works with the JAXBElement class directly, the RESTEasy runtime will select the
      JAXBElementProvider. This provider examines the ParameterizedType value of the JAXBElement in order to select
      the appropriate JAXBContext.
   </para>
   <para>

   </para>
   <para>


   </para>
    <sect1 id="decorators">
        <title>JAXB Decorators</title>
        <para>Resteasy's JAXB providers have a pluggable way to decorate Marshaller and Unmarshaller instances.
        The way it works is that you can write an annotation that can trigger the decoration of a
        Marshaller or Unmarshaller.  Your decorators can do things like set Marshaller or Unmarshaller properties,
        set up validation, stuff like that.  Here's an example.  Let's say we want to have an annotation
        that will trigger pretty-printing, nice formatting, of an XML document.  If we were doing raw
        JAXB, we would set a property on the Marshaller of Marshaller.JAXB_FORMATTED_OUTPUT.  Let's
        write a Marshaller decorator.</para>
        <para>First we define a annotation:</para>
<programlisting>
import org.jboss.resteasy.annotations.Decorator;

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Decorator(processor = PrettyProcessor.class, target = Marshaller.class)
public @interface Pretty {}
</programlisting>
        <para>To get this to work, we must annotate our @Pretty annotation with a meta-annotation called
        @Decorator.  The target() attribute must be the JAXB Marshaller class.  The processor()
        attribute is a class we will write next.</para>
<programlisting><![CDATA[
import org.jboss.resteasy.core.interception.DecoratorProcessor;
import org.jboss.resteasy.annotations.DecorateTypes;

import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.Produces;
import java.lang.annotation.Annotation;

/**
 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
 * @version $Revision: 1 $
 */
@DecorateTypes({"text/*+xml", "application/*+xml"})
public class PrettyProcessor implements DecoratorProcessor<Marshaller, Pretty>
{
    public Marshaller decorate(Marshaller target, Pretty annotation,
                  Class type, Annotation[] annotations, MediaType mediaType)
    {
       target.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    }
}]]>
</programlisting>
    <para>
        The processor implementation must implement the DecoratorProcessor interface and should also be annotated
        with @DecorateTypes.  This annotation specifies what media types the processor can be used with. Now that
        we've defined our annotation and our Processor, we can use it on our JAX-RS resource methods
        or JAXB types as follows:
    </para>
<programlisting>
@GET
@Pretty
@Produces("application/xml")
public SomeJAXBObject get() {...}
</programlisting>
        <para>If you are confused, check the Resteasy source code for the implementation of @XmlHeader</para>
    </sect1>
   <sect1 id="Pluggable_JAXBContext_s_with_ContextResolvers">
      <title>Pluggable JAXBContext's with ContextResolvers</title>

      <para>

         You should not use this feature unless you know what you're doing.
      </para>
      <para>

         Based on the class you are marshalling/unmarshalling, RESTEasy will, by default create and cache JAXBContext
         instances per class type. If you do not want RESTEasy to create JAXBContexts, you can plug-in your own by
         implementing an instance of javax.ws.rs.ext.ContextResolver
      </para>
      <para>

<programlisting>
public interface ContextResolver&lt;T&gt;
{
    T getContext(Class&lt;?&gt; type);
}

@Provider
@Produces("application/xml")
public class MyJAXBContextResolver implements ContextResolver&lt;JAXBContext&gt;
{
    JAXBContext getContext(Class&lt;?&gt; type)
    {
        if (type.equals(WhateverClassIsOverridedFor.class)) return JAXBContext.newInstance()...;
    }
}
</programlisting>
      </para>
      <para>

         You must provide a @Produces annotation to specify the media type the context is meant for. You must also
         make sure to implement ContextResolver&lt;JAXBContext&gt;. This helps the runtime match to the correct
         context resolver. You must also annotate the ContextResolver class with @Provider.
      </para>
      <para>

         There are multiple ways to make this ContextResolver available.
      </para>
      <para>

         <orderedlist>

            <listitem>
               Return it as a class or instance from a javax.ws.rs.core.Application implementation
            </listitem>

            <listitem>
               List it as a provider with resteasy.providers
            </listitem>

            <listitem>
               Let RESTEasy automatically scan for it within your WAR file. See Configuration Guide
            </listitem>

            <listitem>
               Manually add it via ResteasyProviderFactory.getInstance().registerProvider(Class) or
               registerProviderInstance(Object)
            </listitem>

         </orderedlist>

      </para>
      <para>


      </para>
   </sect1>
   <sect1 id="JAXB_+_XML_provider">
      <title>JAXB + XML provider</title>
       <para>
           Resteasy is required to provide JAXB provider support for XML.  It has a few extra annotations
           that can help code your app.
       </para>
       <sect2 id="XmlHeader">
           <title>@XmlHeader and @Stylesheet</title>
           <para>Sometimes when outputting XML documents you may want to set an XML header. Resteasy provides
           the @org.jboss.resteasy.annotations.providers.jaxb.XmlHeader annotation for this.  For example:</para>
<programlisting><![CDATA[
@XmlRootElement
public static class Thing
{
    private String name;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}

@Path("/test")
public static class TestService
{
    @GET
    @Path("/header")
    @Produces("application/xml")
    @XmlHeader("<?xml-stylesheet type='text/xsl' href='${baseuri}foo.xsl' ?>")
    public Thing get()
    {
        Thing thing = new Thing();
        thing.setName("bill");
        return thing;
    }
}]]>
</programlisting>
           <para>
               The @XmlHeader here forces the XML output to have an xml-stylesheet header.  This header
               could also have been put on the Thing class to get the same result.  See the javadocs for more
               details on how you can use substitution values provided by resteasy.
               </para>
           <para>
               Resteasy also has a convenience annotation for stylesheet headers.  For example:
           </para>
<programlisting><![CDATA[
@XmlRootElement
public static class Thing
{
    private String name;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}

@Path("/test")
public static class TestService
{
    @GET
    @Path("/stylesheet")
    @Produces("application/xml")
    @Stylesheet(type="text/css", href="${basepath}foo.xsl")
    @Junk
    public Thing getStyle()
    {
        Thing thing = new Thing();
        thing.setName("bill");
        return thing;
    }
}]]>
</programlisting>
       </sect2>
   </sect1>
   <sect1 id="JAXB_+_JSON_provider">
      <title>JAXB + JSON provider</title>

      <para>

         RESTEasy allows you to marshall JAXB annotated POJOs to and from JSON. This provider wraps the Jettison JSON
         library to accomplish this.  You can obtain more information about Jettison and how it works from
         <ulink url="https://github.com/jettison-json/jettison">https://github.com/jettison-json/jettison</ulink>.
      </para>
      <para>
           To use this integration with Jettision you need to import the resteasy-jettison-provider Maven module.  Older versions
           of RESTEasy used to include this within the resteasy-jaxb-provider but we decided to modularize it more.
       </para>
      <para>
    Jettison has two mapping formats. One is BadgerFish the other is a Jettison
        Mapped Convention format.  The Mapped Convention is the default mapping.
      </para>
      <para>

      </para>
      <para>

         For example, consider this JAXB class:
      </para>
      <para>

<programlisting>
@XmlRootElement(name = "book")
public class Book
{
    private String author;
    private String ISBN;
    private String title;

    public Book()
    {
    }

    public Book(String author, String ISBN, String title)
    {
        this.author = author;
        this.ISBN = ISBN;
        this.title = title;
    }

    @XmlElement
    public String getAuthor()
    {
        return author;
    }

    public void setAuthor(String author)
    {
    this.author = author;
    }

    @XmlElement
    public String getISBN()
    {
        return ISBN;
    }

    public void setISBN(String ISBN)
    {
        this.ISBN = ISBN;
    }

    @XmlAttribute
    public String getTitle()
    {
        return title;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }
}
</programlisting>
      </para>
      <para>


      </para>
      <para>

         This is how the JAXB Book class would be marshalled to JSON using the BadgerFish Convention:
      </para>
      <para>

<programlisting>
{"book":
    {
        "@title":"EJB 3.0",
        "author":{"$":"Bill Burke"},
        "ISBN":{"$":"596529260"}
    }
}
</programlisting>
      </para>
      <para>

         Notice that element values have a map associated with them and to get to the value of the element, you must
         access the &quot;$&quot; variable. Here's an example of accessing the book in Javascript:
      </para>
      <para>

<programlisting>
var data = eval("(" + xhr.responseText + ")");
document.getElementById("zone").innerHTML = data.book.@title;
document.getElementById("zone").innerHTML += data.book.author.$;
</programlisting>
      </para>
      <para>


      </para>
      <para>

         To use the BadgerFish Convention you must use the
         @org.jboss.resteasy.annotations.providers.jaxb.json.BadgerFish annotation on the JAXB class you are
         marshalling/unmarshalling, or, on the JAX-RS resource method or parameter:
      </para>
      <para>

<programlisting>
@BadgerFish
@XmlRootElement(name = "book")
public class Book {...}
</programlisting>
      </para>
      <para>

         If you are returning a book on the JAX-RS method and you don't want to (or can't) pollute your JAXB classes
         with RESTEasy annotations, add the annotation to the JAX-RS method:
      </para>
      <para>

<programlisting>
@BadgerFish
@GET
public Book getBook(...) {...}
</programlisting>
      </para>
      <para>

         If a Book is your input then you put it on the parameter:
      </para>
      <para>

<programlisting>
@POST
public void newBook(@BadgerFish Book book) {...}
</programlisting>
      </para>
      <para>


      </para>
      <para>

         The default Jettison Mapped Convention would return JSON that looked like this:
      </para>
      <para>

<programlisting>
{ "book" :
    {
        "@title":"EJB 3.0",
        "author":"Bill Burke",
        "ISBN":596529260
    }
}
</programlisting>
      </para>
      <para>

         Notice that the @XmlAttribute &quot;title&quot; is prefixed with the '@' character. Unlike BadgerFish, the
         '$' does not represent the value of element text. This format is a bit simpler than the BadgerFish
         convention which is why it was chose as a default. Here's an example of accessing this in Javascript:
      </para>
      <para>

<programlisting>
var data = eval("(" + xhr.responseText + ")");
document.getElementById("zone").innerHTML = data.book.@title;
document.getElementById("zone").innerHTML += data.book.author;
</programlisting>
      </para>
      <para>


      </para>
      <para>

         The Mapped Convention allows you to fine tune the JAXB mapping using the
         @org.jboss.resteasy.annotations.providers.jaxb.json.Mapped annotation. You can provide an XML Namespace to
         JSON namespace mapping. For example, if you defined your JAXB namespace within your package-info.java class like this:
  </para>
<programlisting>
@javax.xml.bind.annotation.XmlSchema(namespace="http://jboss.org/books")
package org.jboss.resteasy.test.books;
</programlisting>
  <para>
      You would have to define a JSON to XML namespace mapping or you would receive an exception of something like this:
  </para>
<programlisting>
java.lang.IllegalStateException: Invalid JSON namespace: http://jboss.org/books
at org.codehaus.jettison.mapped.MappedNamespaceConvention.getJSONNamespace(MappedNamespaceConvention.java:151)
at org.codehaus.jettison.mapped.MappedNamespaceConvention.createKey(MappedNamespaceConvention.java:158)
at org.codehaus.jettison.mapped.MappedXMLStreamWriter.writeStartElement(MappedXMLStreamWriter.java:241)
</programlisting>
      <para>
        To fix this problem you need another annotation, @Mapped.  You use the @Mapped annotation on your JAXB classes, on your JAX-RS resource method, or on
        the parameter you are unmarshalling
  </para>
<programlisting>
import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;

...

@GET
@Produces("application/json")
@Mapped(namespaceMap = {
        @XmlNsMap(namespace = "http://jboss.org/books", jsonName = "books")
})
public Book get() {...}
</programlisting>
      <para>
      Besides mapping XML to JSON namespaces, you can also force @XmlAttribute's to be marshaled as XMLElements.
      </para>
      <para>

<programlisting>
@Mapped(attributeAsElements={"title"})
@XmlRootElement(name = "book")
public class Book {...}
</programlisting>
      </para>
      <para>

         If you are returning a book on the JAX-RS method and you don't want to (or can't) pollute your JAXB classes
         with RESTEasy annotations, add the annotation to the JAX-RS method:
      </para>
      <para>

<programlisting>
@Mapped(attributeAsElements={"title"})
@GET
public Book getBook(...) {...}
</programlisting>
      </para>
      <para>

         If a Book is your input then you put it on the parameter:
      </para>
      <para>

<programlisting>
@POST
public void newBook(@Mapped(attributeAsElements={"title"}) Book book) {...}
</programlisting>
      </para>
      <para>

      </para>
      <para>

      </para>
      <para>

      </para>
      <para>

      </para>
      <para>

      </para>
      <para>


      </para>
   </sect1>
   <sect1 id="JAXB_+_FastinfoSet_provider">
      <title>JAXB + FastinfoSet provider</title>

      <para>

         RESTEasy supports the FastinfoSet mime type with JAXB annotated classes. Fast infoset documents are faster
         to serialize and parse, and smaller in size, than logically equivalent XML documents. Thus, fast infoset
         documents may be used whenever the size and processing time of XML documents is an issue. It is configured
         the same way the XML JAXB provider is so really no other documentation is needed here.
      </para>
       <para>
           To use this integration with Fastinfoset you need to import the resteasy-fastinfoset-provider Maven module.  Older versions
           of RESTEasy used to include this within the resteasy-jaxb-provider but we decided to modularize it more.
       </para>
      <para>


      </para>
   </sect1>
   <sect1 id="JAXB_Collections">
      <title>Arrays and Collections of JAXB Objects</title>
      <para>
         RESTEasy will automatically
         marshal arrays, java.util.Set's, and java.util.List's of JAXB objects to and from XML, JSON, Fastinfoset (or any other new JAXB mapper Restasy comes up with).
      </para>
<programlisting><![CDATA[
@XmlRootElement(name = "customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer
{
    @XmlElement
    private String name;

    public Customer()
    {
    }

    public Customer(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }
}

@Path("/")
public class MyResource
{
    @PUT
    @Path("array")
    @Consumes("application/xml")
    public void putCustomers(Customer[] customers)
    {
        Assert.assertEquals("bill", customers[0].getName());
        Assert.assertEquals("monica", customers[1].getName());
    }

    @GET
    @Path("set")
    @Produces("application/xml")
    public Set<Customer> getCustomerSet()
    {
        HashSet<Customer> set = new HashSet<Customer>();
        set.add(new Customer("bill"));
        set.add(new Customer("monica"));

        return set;
    }

    @PUT
    @Path("list")
    @Consumes("application/xml")
    public void putCustomers(List<Customer> customers)
    {
        Assert.assertEquals("bill", customers.get(0).getName());
        Assert.assertEquals("monica", customers.get(1).getName());
    }
}]]>
</programlisting>
   <para>
      The above resource can publish and receive JAXB objects.  It is assumed that are wrapped in a collection element
   </para>
<programlisting><![CDATA[
<collection>
    <customer><name>bill</name></customer>
    <customer><name>monica</name></customer>
<collection>]]>
</programlisting>
   <para>You can change the namespace URI, namespace tag, and collection element name by using the @org.jboss.resteasy.annotations.providers.jaxb.Wrapped annotation on a parameter or method</para>
<programlisting>
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Wrapped
{
    String element() default "collection";

    String namespace() default "http://jboss.org/resteasy";

    String prefix() default "resteasy";
}
</programlisting>
<para>So, if we wanted to output this XML</para>
<programlisting><![CDATA[
<foo:list xmlns:foo="http://foo.org">
    <customer><name>bill</name></customer>
    <customer><name>monica</name></customer>
</foo:list>]]>
</programlisting>
<para>We would use the @Wrapped annotation as follows: </para>
<programlisting><![CDATA[
@GET
@Path("list")
@Produces("application/xml")
@Wrapped(element="list", namespace="http://foo.org", prefix="foo")
public List<Customer> getCustomerSet()
{
    List<Customer> list = new ArrayList<Customer>();
    list.add(new Customer("bill"));
    list.add(new Customer("monica"));

    return list;
}]]>
</programlisting>

  <sect2 id="collections_on_client">
  <title>Retrieving Collections on the client side</title>
  <para>
  If you try to retrieve a <classname>List</classname>
  or <classname>Set</classname> of JAXB objects in the obvious way on the client side:
  </para>
  
<programlisting>
      Response response = request.get();
      List&lt;Customer&gt; list = response.readEntity(List.class);
</programlisting>

  <para>
  the call to <methodname>readEntity()</methodname> will fail because it has no way of knowing the
  element type <classname>Customer</classname>. The trick is to use an instance of 
  <classname>javax.ws.rs.core.GenericType</classname>:
  </para>
  
<programlisting>
      Response response = request.get();
      GenericType&lt;List&lt;Customer&gt;&gt; genericType = new GenericType&lt;List&lt;Customer&gt;&gt;() {};
      List&lt;Customer&gt; list = response.readEntity(genericType);
</programlisting>

  <para>
  For more information about <classname>GenericType</classname>, please see its javadoc.
  </para>
  
  <para>
  The same trick applies to retrieving a <classname>Set</classname>:
  </para>
  
<programlisting>
      Response response = request.get();
      GenericType&lt;Set&lt;Customer&gt;&gt; genericType = new GenericType&lt;Set&lt;Customer&gt;&gt;() {};
      Set&lt;Customer&gt; set = response.readEntity(genericType);
</programlisting>

  <para>
  On the other hand, <classname>GenericType</classname> is not necessary to retrieve an array of JAXB objects:
  </para>
  
<programlisting>
      Response response = request.get();
      Customer[] array = response.readEntity(Customer[].class);
</programlisting>
  </sect2>

  <sect2 id="json_list">
    <title>JSON and JAXB Collections/arrays</title>
    <para>Resteasy supports using collections with JSON.  It encloses lists, sets, or arrays of returned JAXB objects within a simple
    JSON array.  For example:</para>
<programlisting>
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Foo
{
    @XmlAttribute
    private String test;

    public Foo()
    {
    }

    public Foo(String test)
    {
        this.test = test;
    }

    public String getTest()
    {
        return test;
    }

    public void setTest(String test)
    {
        this.test = test;
    }
}
</programlisting>
 <para>This a List or array of this Foo class would be represented in JSON like this:</para>
<programlisting><![CDATA[
[{"foo":{"@test":"bill"}},{"foo":{"@test":"monica}"}}]]]>
</programlisting>
 <para>It also expects this format for input</para>
  </sect2>
</sect1>
   <sect1 id="JAXB_Map">
      <title>Maps of JAXB Objects</title>
      <para><![CDATA[
         RESTEasy will automatically
         marshal maps of JAXB objects to and from XML, JSON, Fastinfoset (or any other new JAXB mapper Restasy comes up with).
         Your parameter or method return type must be a generic with a String as the key and the JAXB object's type.
     ]]></para>
<programlisting><![CDATA[
@XmlRootElement(namespace = "http://foo.com")
public static class Foo
{
    @XmlAttribute
    private String name;

    public Foo()
    {
    }

    public Foo(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }
}

@Path("/map")
public static class MyResource
{
    @POST
    @Produces("application/xml")
    @Consumes("application/xml")
    public Map<String, Foo> post(Map<String, Foo> map)
    {
        Assert.assertEquals(2, map.size());
        Assert.assertNotNull(map.get("bill"));
        Assert.assertNotNull(map.get("monica"));
        Assert.assertEquals(map.get("bill").getName(), "bill");
        Assert.assertEquals(map.get("monica").getName(), "monica");
        return map;
    }
}]]>
</programlisting>
   <para>
      The above resource can publish and receive JAXB objects within a map.  By default, they are wrapped in a "map" element in the
      default namespace.  Also, each "map" element has zero or more "entry" elements with a "key" attribute.
   </para>
<programlisting><![CDATA[
<map>
    <entry key="bill" xmlns="http://foo.com">
        <foo name="bill"/>
    </entry>
    <entry key="monica" xmlns="http://foo.com">
        <foo name="monica"/>
    </entry>
</map>]]>
</programlisting>
   <para>You can change the namespace URI, namespace prefix and map, entry, and key element and attribute names by using the @org.jboss.resteasy.annotations.providers.jaxb.WrappedMap annotation on a parameter or method</para>
<programlisting>
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface WrappedMap
{
    /**
     * map element name
     */
    String map() default "map";

    /**
     * entry element name *
     */
    String entry() default "entry";

    /**
     * entry's key attribute name
     */
    String key() default "key";

    String namespace() default "";

    String prefix() default "";
}
</programlisting>
<para>So, if we wanted to output this XML</para>
<programlisting><![CDATA[
<hashmap>
    <hashentry hashkey="bill" xmlns:foo="http://foo.com">
        <foo:foo name="bill"/>
    </hashentry>
</map>]]>
</programlisting>
<para>We would use the @WrappedMap annotation as follows: </para>
<programlisting><![CDATA[
@Path("/map")
public static class MyResource
{
    @GET
    @Produces("application/xml")
    @WrappedMap(map="hashmap", entry="hashentry", key="hashkey")
    public Map<String, Foo> get()
    {
        ...
        return map;
    }
}]]>
</programlisting>

  <sect2 id="maps_client_side">
  <title>Retrieving Maps on the client side</title>
  <para>
  If you try to retrieve a <classname>Map</classname>
  of JAXB objects in the obvious way on the client side:
  </para>
  
<programlisting>
      Response response = request.get();
      Map&lt;String, Customer&gt; map = response.readEntity(Map.class);
</programlisting>

  <para>
  the call to <methodname>readEntity()</methodname> will fail because it has no way of knowing the
  element type <classname>Customer</classname>. The trick is to use an instance of 
  <classname>javax.ws.rs.core.GenericType</classname>:
  </para>
  
<programlisting>
      Response response = request.get();
      GenericType&lt;Map&lt;String, Customer&gt; genericType = new GenericType&lt;Map&lt;String, Customer&gt;&gt;() {};
      Map&lt;String, Customer&gt; map = response.readEntity(genericType);
</programlisting>

  <para>
  For more information about <classname>GenericType</classname>, please see its javadoc.
  </para>
  </sect2>

  <sect2 id="json_map">
    <title>JSON and JAXB maps</title>
    <para>Resteasy supports using maps with JSON.  It encloses maps returned JAXB objects within a simple
    JSON map.  For example:</para>
<programlisting>
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Foo
{
    @XmlAttribute
    private String test;

    public Foo()
    {
    }

    public Foo(String test)
    {
        this.test = test;
    }

    public String getTest()
    {
        return test;
    }

    public void setTest(String test)
    {
        this.test = test;
    }
}
</programlisting>
 <para>This a List or array of this Foo class would be represented in JSON like this:</para>
<programlisting><![CDATA[
{ "entry1" : {"foo":{"@test":"bill"}}, "entry2" : {"foo":{"@test":"monica}"}}}]]>
</programlisting>
 <para>It also expects this format for input</para>
  </sect2>
  <sect2 id="JAXB_JSON_problems">
      <title>Possible Problems with Jettison Provider</title>
      <para>
          If you have the resteasy-jackson-provider-xxx.jar in your classpath, the Jackson JSON provider
              will be triggered.  This will screw up code that is dependent on the Jettison JAXB/JSon provider.
              If you had been using the Jettison JAXB/Json providers, you must either remove
              Jackson from your WEB-INF/lib or classpath, or use the @NoJackson annotation on your JAXB classes.
      </para>
  </sect2>
</sect1>
<sect1 id="JAXB_INTERFACES">
   <title>Interfaces, Abstract Classes, and JAXB</title>
   <para>
    Some objects models use abstract classes and interfaces heavily.  Unfortunately, JAXB doesn't work with interfaces
    that are root elements and RESTEasy can't unmarshal parameters that are interfaces or raw abstract classes because
    it doesn't have enough information to create a JAXBContext.  For example:
   </para>
<programlisting>
public interface IFoo {}

@XmlRootElement
public class RealFoo implements IFoo {}

@Path("/jaxb")
public class MyResource {

    @PUT
    @Consumes("application/xml")
    public void put(IFoo foo) {...}
}
</programlisting>
<para>
  In this example, you would get an error from RESTEasy of something like "Cannot find a MessageBodyReader for...".  This is because
  RESTEasy does not know that implementations of IFoo are JAXB classes and doesn't know how to create a JAXBContext for it.  As a workaround,
 RESTEasy allows you to use the JAXB annotation @XmlSeeAlso on the interface to correct the problem.  (NOTE, this will not work with manual, hand-coded JAXB).
</para>
<programlisting>
@XmlSeeAlso(RealFoo.class)
public interface IFoo {}
</programlisting>
<para>
The extra @XmlSeeAlso on IFoo allows RESTEasy to create a JAXBContext that knows how to unmarshal RealFoo instances.
</para>
</sect1>

<sect1 id="configuration">
   <title>Configurating JAXB Marshalling</title>
   <para>
     As a consumer of XML datasets, JAXB is subject to a form of attack
     known as the XXE (Xml eXternal Entity) Attack
     (<ulink url="http://www.securiteam.com/securitynews/6D0100A5PU.html">http://www.securiteam.com/securitynews/6D0100A5PU.html</ulink>),
     in which expanding an external entity causes an unsafe file to be loaded.  Preventing the expansion of 
     external entities is discussed in <xref linkend="Configuring_Document_Marshalling"/>.  The same context
     parameter,
   </para>
   
   <blockquote>
     resteasy.document.expand.entity.references
   </blockquote>
   
   <para>applies to JAXB unmarshallers as well.</para>
   
   
   <para>
     <xref linkend="Configuring_Document_Marshalling"/> also discusses the prohibition of DTDs and the 
     imposition of limits on entity expansion and the number of attributes per element. The context parameters
   </para>
   
   <blockquote>
     resteasy.document.secure.disableDTDs
   </blockquote>
   
   <para>and</para>
   
   <blockquote>
     resteasy.document.secure.processing.feature
   </blockquote>
   
   <para>
     discussed there, and their default values, also apply to the representation of JAXB objects.
   </para>
</sect1>
</chapter>
