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

From Eclipsepedia

Jump to: navigation, search
(Removing all content from page)
 
Line 1: Line 1:
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>
 
  
=Dynamic MOXy: 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:
 
 
<small>
 
* Mapping to JSON and XML data without writing or generating concrete Java classes
 
* Using multiple MOXy metadata files to modularize your metadata
 
* Bootstrapping a DynamicJAXBContext from multiple MOXy metadata files
 
* Using a single DynamicJAXBContext to read both JSON and XML data
 
* Using DynamicEntity APIs to interact with mapped data
 
* Using XPath Predicates to map to an attribute based on another attribute value
 
* 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
 
</small>
 
 
 
The example application uses Dynamic 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 [http://git.eclipse.org/c/eclipselink/examples.git/tree/moxy moxy/dynamic/flickr] in the EclipseLink Examples Git repository.  To clone the complete Examples repository, use the following Git command:
 
 
<div style="width:600px">
 
<source lang="text">
 
git clone git://git.eclipse.org/gitroot/eclipselink/examples.git
 
</source>
 
</div>
 
 
To run the example, just execute Maven:
 
 
<div style="width:600px">
 
<source lang="text">
 
$ mvn
 
</source>
 
</div>
 
 
This will connect to the Internet to read the JSON and XML feeds, and will launch the system browser on the generated HTML file.
 
 
<div style="width:850px">
 
{{note|Proxy Connections|If you require a proxy server to access the Internet, check the '''&lt;systemProperties&gt;''' section of '''pom.xml'''.}}
 
</div>
 
 
 
==Background: DynamicEntities==
 
 
Instead of using actual Java classes (such as Customer.class or Address.class), Dynamic MOXy generates (in-memory) '''DynamicTypes''' defined by the metadata provided.  An "instance" of a '''DynamicType''' is called a '''DynamicEntity''', which provides a simple '''get(propertyName) / set(propertyName, propertyValue)''' API to manipulate data.
 
 
For more information, and to learn about other ways that Dynamic MOXy can be used, see [http://www.eclipse.org/eclipselink/documentation/2.4/moxy/dynamic_jaxb.htm Using Dynamic JAXB] in the EclipseLink documentation.
 
 
 
==Getting JSON from Reddit==
 
 
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</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'''.
 
 
 
==Mapping to Reddit JSON==
 
 
The MOXy 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">
 
<source lang="xml">
 
<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>
 
</source>
 
</div>
 
 
 
==Getting XML from Flickr==
 
 
Flickr provides a public XML feed using the following URL format:
 
 
<code>http://api.flickr.com/services/feeds/photos_public.gne?safe_search=1&tags=science</code>
 
 
This will return us XML in the [[#Flickr XML Format|following format]].  For each '''entry''', we want to locate two '''link''' elements, based on their attributes:
 
 
* '''link''' with '''@type='image/jpeg'''' : the '''@href''' attribute points to the actual image
 
* '''link''' with '''@rel='alternate'''' : the '''@href''' attribute points to the corresponding Flickr page
 
 
 
==Mapping to Flickr XML==
 
 
MOXy metadata can also be provided in a JSON file, which can be more compact than XML.  The metadata that defines our mappings to Flickr's XML output is stored in the '''bindings-flickr.json''' 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''' contains two URLs: one to the actual image, and one to the Flickr page for that image..
 
 
<div style="width:1250px">
 
<source lang="text">
 
{
 
  "package-name" : "eclipselink.example.moxy.dynamic.flickr",
 
  "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",
 
              "type" : "java.lang.String",
 
              "xml-path" : "title/text()"
 
            }, {
 
              "java-attribute" : "items",
 
              "container-type" : "java.util.ArrayList",
 
              "type" : "eclipselink.example.moxy.dynamic.flickr.FlickrItem",
 
              "xml-path" : "entry"
 
            } ]
 
        }
 
      }, {
 
        "name" : "eclipselink.example.moxy.dynamic.flickr.FlickrItem",
 
        "java-attributes" : {
 
            "xml-attribute" : [ {
 
              "java-attribute" : "flickrPage",
 
              "type" : "java.lang.String",
 
              "xml-path" : "link[@rel='alternate']/@href"
 
            }, {
 
              "java-attribute" : "imageUrl",
 
              "type" : "java.lang.String",
 
              "xml-path" : "link[@type='image/jpeg']/@href"
 
            } ]
 
        }
 
      } ]
 
  }
 
}
 
</source>
 
</div>
 
 
<div style="width:1000px">
 
{{tip|MOXy Metadata in JSON Format|The following code can be used to convert an EclipseLink bindings file in XML format, to the same bindings in JSON format.
 
<source lang="java">
 
ClassLoader loader = Thread.currentThread().getContextClassLoader();
 
InputStream bindingsXml = loader.getResourceAsStream("META-INF/bindings-flickr.xml");
 
JAXBContext ctx = JAXBContext.newInstance("org.eclipse.persistence.jaxb.xmlmodel");
 
Object bindings = ctx.createUnmarshaller().unmarshal(bindingsXml);
 
 
Marshaller m = ctx.createMarshaller();
 
m.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
 
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
 
m.marshal(bindings, System.out);
 
</source>
 
}}
 
</div>
 
 
 
 
==init()==
 
 
At startup, we gather our three metadata files and pass them to '''DynamicJAXBContextFactory''' to create the '''DynamicJAXBContext'''.
 
 
<div style="width:1250px">
 
<source lang="java">
 
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 '''RedditResults'''.
 
 
<div style="width:1250px">
 
<source lang="java">
 
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();
 
 
DynamicEntity redditResults = u.unmarshal(new StreamSource(REDDIT_URL), redditResultsClass).getValue();
 
</source>
 
</div>
 
 
 
==findFlickrResults()==
 
 
Now that we have '''RedditResults''', we will iterate over its '''RedditPosts''' and construct a Flickr query URL for each one, using keywords from the post's title.  We'll then unmarshal from the query URL to get an instance of our '''FlickrResults'''.  Because Flickr is providing a standard XML format, a simple default '''Unmarshaller''' is all that is necessary.
 
 
<div style="width:1250px">
 
<source lang="java">
 
DynamicEntity redditPost = ...;
 
String keywords = extractKeywords(post.get("title").toString());
 
 
String flickrUrlString = FLICKR_URL + keywords;
 
InputStream flickrStream = new URL(flickrUrlString).openConnection().getInputStream();
 
 
Unmarshaller u = context.createUnmarshaller();
 
DynamicEntity flickrResults = (DynamicEntity) u.unmarshal(flickrStream);
 
</source>
 
</div>
 
 
 
==writeHtml()==
 
 
Finally, we take the information from our '''RedditResults''' and '''FlickerResults''' and put it together into an '''HtmlPage''' object, defined in '''[[#bindings-html.xml|bindings-html.xml]]'''.  We then marshal this to a '''File'''.  In addition to specifying that our '''Marshaller''' should use  formatted output, we also use '''(Marshaller.JAXB_FRAGMENT, true)''', to omit the '''<?xml ...''' preamble from our HTML file.
 
 
<div style="width:1250px">
 
<source lang="java">
 
DynamicEntity html = context.newDynamicEntity("eclipselink.example.moxy.dynamic.flickr.HtmlPage");
 
html.set("title", "TopLink MOXy - Dynamic JAXB");
 
html.set("css", "style.css");
 
...
 
 
DynamicEntity body = context.newDynamicEntity("eclipselink.example.moxy.dynamic.flickr.HtmlBody");
 
body.set("title", "Reddit /" + SUBREDDIT + " - Today's Top Posts");
 
...
 
 
DynamicEntity redditLink = context.newDynamicEntity("eclipselink.example.moxy.dynamic.flickr.HtmlTextLink");
 
redditLink.set("url", redditPost.get("url"));
 
redditLink.set("title", redditPost.get("title"));
 
...
 
 
DynamicEntity flickrDescription = context.newDynamicEntity("eclipselink.example.moxy.dynamic.flickr.HtmlText");
 
flickrDescription.set("text", flickrResults.get("description"));
 
...
 
 
DynamicEntity flickrImageLink = context.newDynamicEntity("eclipselink.example.moxy.dynamic.flickr.HtmlImageLink");
 
flickrImageLink.set("url", flickrItem.get("imageUrl"));
 
flickrImageLink.set("image", flickrItem.get("imageUrl"));
 
flickrImageLink.set("height", Integer.valueOf(80));
 
...
 
 
html.set("body", body);
 
 
Marshaller m = context.createMarshaller();
 
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
m.setProperty(Marshaller.JAXB_FRAGMENT, true);
 
m.marshal(html, outputFile);
 
</source>
 
</div>
 
 
 
==Appendix==
 
 
===bindings-html.xml===
 
 
The following metadata is used to generate an HTML structure programatically.  The '''HtmlBody''' object contains a collection of '''HtmlDiv''', which in turn has a collection of '''HtmlItem'''.  Inheritance is used to model '''HtmlItem''' and its sub-types '''HtmlText''', '''HtmlLink''', '''HtmlTextLink''' and '''HtmlImageLink'''.
 
 
<div style="width:1250px">
 
<source lang="xml">
 
<?xml version="1.0" encoding="UTF-8"?>
 
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="eclipselink.example.moxy.dynamic.flickr">
 
  <java-types>
 
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.HtmlPage">
 
      <xml-root-element name="html" />
 
      <java-attributes>
 
        <xml-element java-attribute="title" xml-path="head/title/text()" type="java.lang.String" />
 
        <xml-attribute java-attribute="css" xml-path="head/link/@href" type="java.lang.String" />
 
        <xml-attribute java-attribute="rel" xml-path="head/link/@rel" type="java.lang.String" />
 
        <xml-attribute java-attribute="type" xml-path="head/link/@type" type="java.lang.String" />
 
        <xml-attribute java-attribute="media" xml-path="head/link/@media" type="java.lang.String" />
 
        <xml-element java-attribute="body" xml-path="body" type="eclipselink.example.moxy.dynamic.flickr.HtmlBody" />
 
      </java-attributes>
 
    </java-type>
 
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.HtmlBody">
 
      <java-attributes>
 
        <xml-element java-attribute="title" xml-path="p/h1/text()" type="java.lang.String" />
 
        <xml-element java-attribute="divs" xml-path="p/p" type="eclipselink.example.moxy.dynamic.flickr.HtmlDiv" container-type="java.util.ArrayList" />
 
      </java-attributes>
 
    </java-type>
 
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.HtmlDiv">
 
      <java-attributes>
 
        <xml-attribute java-attribute="id" xml-path="div/@id" type="java.lang.String" />
 
        <xml-element java-attribute="span" type="eclipselink.example.moxy.dynamic.flickr.HtmlItem" container-type="java.util.ArrayList">
 
          <xml-element-wrapper name="div" />
 
        </xml-element>
 
      </java-attributes>
 
    </java-type>
 
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.HtmlItem" />
 
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.HtmlText" super-type="eclipselink.example.moxy.dynamic.flickr.HtmlItem">
 
      <java-attributes>
 
        <xml-element java-attribute="text" xml-path="p/small/text()" type="java.lang.String" />
 
      </java-attributes>
 
    </java-type>
 
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.HtmlLink" super-type="eclipselink.example.moxy.dynamic.flickr.HtmlItem">
 
      <java-attributes>
 
        <xml-attribute java-attribute="url" xml-path="a/@href" type="java.lang.String" />
 
      </java-attributes>
 
    </java-type>
 
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.HtmlTextLink" super-type="eclipselink.example.moxy.dynamic.flickr.HtmlLink">
 
      <java-attributes>
 
        <xml-element java-attribute="title" xml-path="a/text()" type="java.lang.String" />
 
      </java-attributes>
 
    </java-type>
 
 
    <java-type name="eclipselink.example.moxy.dynamic.flickr.HtmlImageLink" super-type="eclipselink.example.moxy.dynamic.flickr.HtmlLink">
 
      <java-attributes>
 
        <xml-attribute java-attribute="image" xml-path="a/img/@src" type="java.lang.String" />
 
        <xml-attribute java-attribute="width" xml-path="a/img/@width" type="java.lang.Integer" />
 
        <xml-attribute java-attribute="height" xml-path="a/img/@height" type="java.lang.Integer" />
 
      </java-attributes>
 
    </java-type>
 
 
  </java-types>
 
</xml-bindings>
 
</source>
 
</div>
 
 
 
===Reddit JSON Format===
 
 
<div style="width:1250px">
 
<source lang="text">
 
{
 
  "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
 
        }
 
      },
 
      ...
 
</source>
 
</div>
 
 
 
===Flickr XML Format===
 
 
<div style="width:1250px">
 
<source lang="text">
 
<?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>
 
  ...
 
</source>
 
</div>
 

Latest revision as of 16:29, 3 June 2013