Difference between revisions of "User:Rick.barkhouse.oracle.com/Test1"

From Eclipsepedia

Jump to: navigation, search
Line 1: Line 1:
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>  
+
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>
  
 
=Dynamic JAXB: Flickr Example=
 
=Dynamic JAXB: Flickr Example=
Line 6: Line 6:
  
 
* Mapping to JSON and XML data without writing or generating concrete Java classes
 
* Mapping to JSON and XML data without writing or generating concrete Java classes
* Using multiple EclipseLink binding files to modularize your metadata
+
* Using multiple EclipseLink metadata files to modularize your metadata
 
* Bootstrapping a DynamicJAXBContext from multiple EclipseLink metadata files
 
* Bootstrapping a DynamicJAXBContext from multiple EclipseLink metadata files
 
* Using a single DynamicJAXBContext to read both JSON and XML data
 
* Using a single DynamicJAXBContext to read both JSON and XML data
Line 38: Line 38:
  
 
<div style="width:850px">
 
<div style="width:850px">
{{note|Proxy Connections|If you require a proxy server to access the Internet, check the <code>&lt;systemProperties&gt;</code> section of <code>pom.xml</code>.}}
+
{{note|Proxy Connections|If you require a proxy server to access the Internet, check the '''&lt;systemProperties&gt;''' section of '''pom.xml'''.}}
 
</div>
 
</div>
  
Line 46: Line 46:
 
Reddit provides a public JSON feed using the following URL format:
 
Reddit provides a public JSON feed using the following URL format:
  
<code>
+
'''
 
http://www.reddit.com/r/science/top/.json?sort=top&t=day&limit=5
 
http://www.reddit.com/r/science/top/.json?sort=top&t=day&limit=5
</code>
+
'''
  
 
This will return us JSON in the [[#Reddit JSON Format|following format]].  For this example, we are primarily interested in the '''title''' and '''url''' fields of '''data/children/data'''.
 
This will return us JSON in the [[#Reddit JSON Format|following format]].  For this example, we are primarily interested in the '''title''' and '''url''' fields of '''data/children/data'''.
Line 55: Line 55:
 
==Mapping to Reddit JSON==
 
==Mapping to Reddit JSON==
  
The EclipseLink metadata that defines our mappings to the JSON output is stored in the '''bindings-reddit.xml''' file.  We define a '''RedditResults''' class that will hold a collection of '''RedditPost''' objects.  Each '''RedditPost''' maps to the '''title''' and '''url''' returned by Reddit.
+
The EclipseLink metadata that defines our mappings to the JSON output is stored in the '''bindings-reddit.xml''' file.  We define a '''RedditResults''' class that will hold a collection of '''RedditPost''' objects.  Each '''RedditPost''' maps to the '''title''' and '''url''' returned by Reddit.  Here, we are essentially designing virtual "classes" that will be mapped to the information we are interested in.
  
 
<div style="width:1250px">
 
<div style="width:1250px">
Line 65: Line 65:
 
         <java-attributes>
 
         <java-attributes>
 
             <xml-element java-attribute="posts" xml-path="data/children" container-type="java.util.ArrayList"
 
             <xml-element java-attribute="posts" xml-path="data/children" container-type="java.util.ArrayList"
                         type="eclipselink.example.moxy.dynamic.flickr.RedditPost" />              
+
                         type="eclipselink.example.moxy.dynamic.flickr.RedditPost" />
 
         </java-attributes>
 
         </java-attributes>
 
     </java-type>
 
     </java-type>
   
+
 
 
     <java-type name="eclipselink.example.moxy.dynamic.flickr.RedditPost">
 
     <java-type name="eclipselink.example.moxy.dynamic.flickr.RedditPost">
 
         <java-attributes>
 
         <java-attributes>
             <xml-element java-attribute="title" xml-path="data/title/text()" type="java.lang.String"/>              
+
             <xml-element java-attribute="title" xml-path="data/title/text()" type="java.lang.String"/>
             <xml-element java-attribute="url" xml-path="data/url/text()" type="java.lang.String"/>              
+
             <xml-element java-attribute="url" xml-path="data/url/text()" type="java.lang.String"/>
 
         </java-attributes>
 
         </java-attributes>
 
     </java-type>
 
     </java-type>
Line 85: Line 85:
 
Flickr provides a public XML feed using the following URL format:
 
Flickr provides a public XML feed using the following URL format:
  
<code>
+
'''
 
http://api.flickr.com/services/feeds/photos_public.gne?tags=science
 
http://api.flickr.com/services/feeds/photos_public.gne?tags=science
</code>
+
'''
  
 
This will return us XML in the [[#Flickr XML Format|following format]].  For each '''entry''', we want to locate the '''link''' element that has '''@type='image/jpeg'''', and extract the '''href''' attribute, pointing to the actual image.
 
This will return us XML in the [[#Flickr XML Format|following format]].  For each '''entry''', we want to locate the '''link''' element that has '''@type='image/jpeg'''', and extract the '''href''' attribute, pointing to the actual image.
Line 105: Line 105:
 
         <xml-root-element name="feed"/>
 
         <xml-root-element name="feed"/>
 
         <java-attributes>
 
         <java-attributes>
             <xml-element java-attribute="description" xml-path="title/text()" type="java.lang.String"/>              
+
             <xml-element java-attribute="description" xml-path="title/text()" type="java.lang.String"/>
 
             <xml-element java-attribute="items" xml-path="entry" container-type="java.util.ArrayList"
 
             <xml-element java-attribute="items" xml-path="entry" container-type="java.util.ArrayList"
 
                         type="eclipselink.example.moxy.dynamic.flickr.FlickrItem"/>
 
                         type="eclipselink.example.moxy.dynamic.flickr.FlickrItem"/>
Line 113: Line 113:
 
     <java-type name="eclipselink.example.moxy.dynamic.flickr.FlickrItem">
 
     <java-type name="eclipselink.example.moxy.dynamic.flickr.FlickrItem">
 
         <java-attributes>
 
         <java-attributes>
             <xml-attribute java-attribute="imageUrl" xml-path="link[@type='image/jpeg']/@href" type="java.lang.String"/>              
+
             <xml-attribute java-attribute="imageUrl" xml-path="link[@type='image/jpeg']/@href" type="java.lang.String"/>
 
         </java-attributes>
 
         </java-attributes>
 
     </java-type>
 
     </java-type>
Line 120: Line 120:
 
</source>
 
</source>
 
</div>
 
</div>
 +
 +
 +
==init()==
 +
 +
At startup, we gather our three EclipseLink metadata files and pass them to '''DynamicJAXBContextFactory''' to create the '''JAXBContext'''.
 +
 +
<div style="width:1250px">
 +
<source lang="text">
 +
ClassLoader loader = Thread.currentThread().getContextClassLoader();
 +
 +
InputStream redditBindings = loader.getResourceAsStream("META-INF/bindings-reddit.xml");
 +
InputStream flickrBindings = loader.getResourceAsStream("META-INF/bindings-flickr.xml");
 +
InputStream htmlBindings = loader.getResourceAsStream("META-INF/bindings-html.xml");
 +
 +
ArrayList<InputStream> dataBindings = new ArrayList<InputStream>(3);
 +
dataBindings.add(redditBindings);
 +
dataBindings.add(flickrBindings);
 +
dataBindings.add(htmlBindings);
 +
 +
Map<String, Object> properties = new HashMap<String, Object>();
 +
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, dataBindings);
 +
context = DynamicJAXBContextFactory.createContextFromOXM(null, properties);
 +
</source>
 +
</div>
 +
 +
 +
==readRedditPosts()==
 +
 +
To unmarshal Reddit's JSON, we create a new '''Unmarshaller''', and specify that our media type is JSON.
 +
 +
We also specify '''(JSON_INCLUDE_ROOT, false)''', because there is no root element in this JSON format.  Because of this, we need to use an '''unmarshal()''' method that takes a '''Class''' parameter, indicating the type of object we are unmarshalling.  We can obtain our "virtual" class by creating a new '''DynamicEntity''' of type
 +
 +
 +
 +
<div style="width:1250px">
 +
<source lang="text">
 +
Unmarshaller u = context.createUnmarshaller();
 +
u.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
 +
u.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
 +
 +
Class<? extends DynamicEntity> redditResultsClass = context.newDynamicEntity("eclipselink.example.moxy.dynamic.flickr.RedditResults").getClass();
 +
 +
System.out.println();
 +
System.out.print("Reading Today's Hot Topics from Reddit r/" + SUBREDDIT + "... ");
 +
DynamicEntity redditResults = u.unmarshal(new StreamSource(REDDIT_URL), redditResultsClass).getValue();
 +
System.out.println("Done.");
 +
 +
ArrayList<DynamicEntity> posts = redditResults.get("posts");
 +
for (DynamicEntity post : posts) {
 +
  redditMap.put(post.get("url"), post);
 +
}
 +
</source>
 +
</div>
 +
 +
 +
  
  

Revision as of 15:20, 29 May 2013

Dynamic JAXB: Flickr Example

This example will demonstrate how to use MOXy's Dynamic JAXB features to work with public JSON and XML feeds, without having to create concrete Java classes. The following concepts are demonstrated:

  • Mapping to JSON and XML data without writing or generating concrete Java classes
  • Using multiple EclipseLink metadata files to modularize your metadata
  • Bootstrapping a DynamicJAXBContext from multiple EclipseLink metadata files
  • Using a single DynamicJAXBContext to read both JSON and XML data
  • Using DynamicEntity APIs to interact with mapped data
  • Using UnmarshallerProperties.JSON_INCLUDE_ROOT to read JSON that does not have a root element
  • Using Marshaller.JAXB_FRAGMENT to omit the XML preamble when writing
  • Using XPath Predicate mapping to map to an element based on an attribute value

This example uses MOXy to read a JSON stream from Reddit, an XML stream from Flickr, and uses the data from both to create an HTML file.


Running the Example

The full code for this example is available under moxy/dynamic/flickr in the EclipseLink Examples Git repository:

git clone git://git.eclipse.org/gitroot/eclipselink/examples.git

To run the example, just execute Maven:

$ mvn

This will connect to the Internet to read the JSON and XML feeds, and will launch the system browser on the generated HTML file.

Note.png
Proxy Connections
If you require a proxy server to access the Internet, check the <systemProperties> section of pom.xml.


Getting JSON from Reddit

Reddit provides a public JSON feed using the following URL format:

http://www.reddit.com/r/science/top/.json?sort=top&t=day&limit=5

This will return us JSON in the following format. For this example, we are primarily interested in the title and url fields of data/children/data.


Mapping to Reddit JSON

The EclipseLink metadata that defines our mappings to the JSON output is stored in the bindings-reddit.xml file. We define a RedditResults class that will hold a collection of RedditPost objects. Each RedditPost maps to the title and url returned by Reddit. Here, we are essentially designing virtual "classes" that will be mapped to the information we are interested in.

<java-types>
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.RedditResults">
        <xml-root-element/>
        <java-attributes>
            <xml-element java-attribute="posts" xml-path="data/children" container-type="java.util.ArrayList"
                         type="eclipselink.example.moxy.dynamic.flickr.RedditPost" />
        </java-attributes>
    </java-type>
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.RedditPost">
        <java-attributes>
            <xml-element java-attribute="title" xml-path="data/title/text()" type="java.lang.String"/>
            <xml-element java-attribute="url" xml-path="data/url/text()" type="java.lang.String"/>
        </java-attributes>
    </java-type>
 
</java-types>


Getting XML from Flickr

Flickr provides a public XML feed using the following URL format:

http://api.flickr.com/services/feeds/photos_public.gne?tags=science

This will return us XML in the following format. For each entry, we want to locate the link element that has @type='image/jpeg', and extract the href attribute, pointing to the actual image.


Mapping to Flickr XML

The EclipseLink metadata that defines our mappings to Flickr's XML output is stored in the bindings-flickr.xml file. We define a FlickrResults class that will hold a collection of FlickrItem objects, as well as a description of the search being performed. Each FlickrItem simply contains a URL string pointing to an image file.

<xml-schema element-form-default="QUALIFIED" namespace="http://www.w3.org/2005/Atom"/>
 
<java-types>
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.FlickrResults">
        <xml-root-element name="feed"/>
        <java-attributes>
            <xml-element java-attribute="description" xml-path="title/text()" type="java.lang.String"/>
            <xml-element java-attribute="items" xml-path="entry" container-type="java.util.ArrayList"
                         type="eclipselink.example.moxy.dynamic.flickr.FlickrItem"/>
        </java-attributes>
    </java-type>
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.FlickrItem">
        <java-attributes>
            <xml-attribute java-attribute="imageUrl" xml-path="link[@type='image/jpeg']/@href" type="java.lang.String"/>
        </java-attributes>
    </java-type>
 
</java-types>


init()

At startup, we gather our three EclipseLink metadata files and pass them to DynamicJAXBContextFactory to create the JAXBContext.

ClassLoader loader = Thread.currentThread().getContextClassLoader();
 
InputStream redditBindings = loader.getResourceAsStream("META-INF/bindings-reddit.xml");
InputStream flickrBindings = loader.getResourceAsStream("META-INF/bindings-flickr.xml");
InputStream htmlBindings = loader.getResourceAsStream("META-INF/bindings-html.xml");
 
ArrayList<InputStream> dataBindings = new ArrayList<InputStream>(3);
dataBindings.add(redditBindings);
dataBindings.add(flickrBindings);
dataBindings.add(htmlBindings);
 
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, dataBindings);
context = DynamicJAXBContextFactory.createContextFromOXM(null, properties);


readRedditPosts()

To unmarshal Reddit's JSON, we create a new Unmarshaller, and specify that our media type is JSON.

We also specify (JSON_INCLUDE_ROOT, false), because there is no root element in this JSON format. Because of this, we need to use an unmarshal() method that takes a Class parameter, indicating the type of object we are unmarshalling. We can obtain our "virtual" class by creating a new DynamicEntity of type


Unmarshaller u = context.createUnmarshaller();
u.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
u.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
 
Class<? extends DynamicEntity> redditResultsClass = context.newDynamicEntity("eclipselink.example.moxy.dynamic.flickr.RedditResults").getClass();
 
System.out.println();
System.out.print("Reading Today's Hot Topics from Reddit r/" + SUBREDDIT + "... ");
DynamicEntity redditResults = u.unmarshal(new StreamSource(REDDIT_URL), redditResultsClass).getValue();
System.out.println("Done.");
 
ArrayList<DynamicEntity> posts = redditResults.get("posts");
for (DynamicEntity post : posts) {
   redditMap.put(post.get("url"), post);
}



Appendix - Data Formats

Reddit JSON Format

{
  "kind":"Listing",
  "data":{
    "modhash":"qdohhwkxss9091dc13eed91db333b619420a787aa2a39b3982",
    "children":[
      {
        "kind":"t3",
        "data":{
          "domain":"news.mongabay.com",
          "banned_by":null,
          "media_embed":{
 
          },
          "subreddit":"science",
          "selftext_html":null,
          "selftext":"",
          "likes":null,
          "link_flair_text":null,
          "id":"1f5jv3",
          "clicked":false,
          "title":"Plants re-grow after 500 years under the ice",
          "media":null,
          "score":2665,
          "approved_by":null,
          "over_18":false,
          "hidden":false,
          "thumbnail":"",
          "subreddit_id":"t5_mouw",
          "edited":false,
          "link_flair_css_class":null,
          "author_flair_css_class":null,
          "downs":5569,
          "saved":false,
          "is_self":false,
          "permalink":"/r/science/comments/1f5jv3/plants_regrow_after_500_years_under_the_ice/",
          "name":"t3_1f5jv3",
          "created":1369712639.0,
          "url":"http://news.mongabay.com/2013/0527-dimitrova-ice-plants.html",
          "author_flair_text":null,
          "author":"soyuz-capsule",
          "created_utc":1369683839.0,
          "ups":8234,
          "num_comments":178,
          "num_reports":null,
          "distinguished":null
        }
      },
      ...

</div


Flickr XML Format

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:flickr="urn:flickr:user">
  <title>Recent Uploads tagged science</title>
  <link rel="self" href="http://api.flickr.com/services/feeds/photos_public.gne?tags=science" />
  <link rel="alternate" type="text/html" href="http://www.flickr.com/photos/tags/science/" />
  <id>tag:flickr.com,2005:/photos/public/tagged/all/science</id>
  <icon>http://l.yimg.com/g/images/buddyicon.gif</icon>
  <subtitle />
  <updated>2013-05-28T17:54:28Z</updated>
  <generator uri="http://www.flickr.com/">Flickr</generator>
  <entry>
    <title>Space Shuttle Endeavour</title>
    <link rel="alternate" type="text/html" href="http://www.flickr.com/photos/d3capmode/8869663050/" />
    <id>tag:flickr.com,2005:/photo/8869663050</id>
    <published>2013-05-28T17:54:28Z</published>
    <updated>2013-05-28T17:54:28Z</updated>
    <flickr:date_taken>2013-05-26T14:11:25-08:00</flickr:date_taken>
    <dc:date.Taken>2013-05-26T14:11:25-08:00</dc:date.Taken>
    <content type="html">&lt;p&gt;&lt;a href="http://www.flickr.com/people/d3capmode/"&gt;Jason Scheier&lt;/a&gt; posted a photo:</content>
    <author>
      <name>Jason Scheier</name>
      <uri>http://www.flickr.com/people/d3capmode/</uri>
      <flickr:nsid>49842342@N07</flickr:nsid>
      <flickr:buddyicon>http://farm6.staticflickr.com/5452/buddyicons/49842342@N07.jpg?1369198532#49842342@N07</flickr:buddyicon>
    </author>
    <link rel="enclosure" type="image/jpeg" href="http://farm8.staticflickr.com/7366/8869663050_e0aa1331fe_b.jpg" />
    <category term="park" scheme="http://www.flickr.com/photos/tags/" />
    <category term="love" scheme="http://www.flickr.com/photos/tags/" />
    <category term="los" scheme="http://www.flickr.com/photos/tags/" />
    <category term="memorial" scheme="http://www.flickr.com/photos/tags/" />
    <category term="day" scheme="http://www.flickr.com/photos/tags/" />
    <category term="control" scheme="http://www.flickr.com/photos/tags/" />
    <category term="angeles" scheme="http://www.flickr.com/photos/tags/" />
    <category term="space" scheme="http://www.flickr.com/photos/tags/" />
    <category term="engineering" scheme="http://www.flickr.com/photos/tags/" />
    <category term="center" scheme="http://www.flickr.com/photos/tags/" />
    <category term="science" scheme="http://www.flickr.com/photos/tags/" />
    <category term="nasa" scheme="http://www.flickr.com/photos/tags/" />
    <category term="exposition" scheme="http://www.flickr.com/photos/tags/" />
    <category term="shuttle" scheme="http://www.flickr.com/photos/tags/" />
    <category term="mission" scheme="http://www.flickr.com/photos/tags/" />
    <category term="jpl" scheme="http://www.flickr.com/photos/tags/" />
    <category term="starship" scheme="http://www.flickr.com/photos/tags/" />
    <category term="endeavour" scheme="http://www.flickr.com/photos/tags/" />
  </entry>
  <entry>
  ...