<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>jax-rs &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/jax-rs/</link>
	<description>Feed of posts on WordPress.com tagged "jax-rs"</description>
	<pubDate>Sun, 06 Dec 2009 08:34:24 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Dojo and JAX-RS &ndash; invocation &amp; imprecation]]></title>
<link>http://djna.wordpress.com/2009/12/04/dojo-and-jax-rs-invocation-imprecation/</link>
<pubDate>Fri, 04 Dec 2009 11:37:31 +0000</pubDate>
<dc:creator>djna</dc:creator>
<guid>http://djna.wordpress.com/2009/12/04/dojo-and-jax-rs-invocation-imprecation/</guid>
<description><![CDATA[Having used Apache Wink to&#160; implement my basic JAX-RS service, which simply retrieves some info]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Having <a href="http://djna.wordpress.com/2009/12/02/jax-rs-with-apache-wink/">used Apache Wink</a> to&#160; implement my basic JAX-RS service, which simply retrieves some information from Library, details of a Book Edition given its ISBN, I next want to implement an operation to add an Edition to the library. This operation will use a POST method to the resource</p>
<p>&#160;&#160;&#160; <a href="http://myhost/LibraryWink/library/editions">http://myhost/LibraryWink/library/editions</a></p>
<p>that is, the resource that specifies that entire collection. Once again, the JAX-RS programming model makes the implementation of the service operation very easy, but I stumbled across a minor annoyance in testing the operation from Dojo, so in this posting I’ll take a side trip into the <a href="http://docs.dojocampus.org/welcome">Dojo</a> JavaScript libraries.</p>
<h2>JAX-RS POST implementation</h2>
<p>I already have a resource implementation class and so I just need to add a method to process the POST request</p>
<p><font face="Courier n" size="1">@POST      <br />@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})       <br />@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})       <br />public BookEdition addNewEdition(BookEdition edition) {       <br />&#160;&#160;&#160; return EditionStore.getInstance().addEdition(edition);       <br />}</font></p>
<p><font face="Courier n" size="1">There are a few points to note here.</font></p>
<ul>
<li><font size="1">The input parameter <strong>edition</strong> is not annotated. Contrast this with the GET example,&#160; </font><font size="1"><strong>getEditionByIsbn(</strong></font><font size="1"><strong>@PathParam(&#34;isbn&#34;) String isbn),</strong> which enabled access to an element from the URI. Here the <strong>edition</strong> parameter is mapped to the request body, that is the content which is <strong>POST</strong>ed. Such a parameter is termed an <strong>Entity</strong> parameter. A method may have at most one entity parameter.</font> </li>
<li><font size="1">I have decided to permit both JSON and XML payloads to be Posted. JSON is very convenient from Dojo, as we shall see, but other clients may prefer XML. The Wink JAX-RS implementation will deal with deserializing JSON or XML depending upon the MediaType of the request. </font></li>
<li><font size="1">As a design decision, I have chosen to return the state representation of the added edition. In this case it’s overkill as the state was passed in and we make no modifications in adding it to the Library. However in general it’s quite possible that there is some enrichment of data as it is inserted into the store. Hence I use the general pattern of returning a representation of what has been stored.</font> </li>
</ul>
<h2>Testing with Poster</h2>
<p>We can quickly test this method using a Firefox extension: <a href="http://code.google.com/p/poster-extension/">Poster</a>. </p>
<p><a href="http://djna.files.wordpress.com/2009/12/posterpost.jpg"><img title="PosterPost" style="display:inline;border-width:0;" height="483" alt="PosterPost" src="http://djna.files.wordpress.com/2009/12/posterpost_thumb.jpg?w=412&#038;h=483" width="412" border="0" /></a> </p>
<p>Specifying an Edition in XML</p>
<p>&#160;&#160;&#160; <font size="1">&#60;Edition&#62;      <br />&#160;&#160;&#160;&#160;&#160; &#60;title&#62;Invincible&#60;/title&#62;       <br />&#160;&#160;&#160;&#160;&#160; &#60;author&#62;John Power&#60;/author&#62;       <br />&#160;&#160;&#160;&#160;&#160; &#60;isbn&#62;B000NZ8Y9Q&#60;/isbn&#62;       <br />&#160;&#160;&#160;&#160; &#60;/Edition&#62;</font></p>
<p>and the content type <strong>application/xml. </strong>The response is as expected, containing a representation of the Edition we added. In the same way, we can provide a JSON payload</p>
<p>&#160;&#160;&#160; <font size="1">{&#34;Edition&#34;:      <br />&#160;&#160;&#160;&#160;&#160; {&#34;title&#34;: &#34;Invincible&#34;,       <br />&#160;&#160;&#160;&#160;&#160;&#160; &#34;author&#34;: &#34;John Power&#34;,       <br />&#160;&#160;&#160;&#160;&#160; &#34;isbn&#34;:&#34;B000NZ8Y9Q&#34;       <br />&#160;&#160;&#160; }}</font></p>
<p>And content type <strong>application/json</strong>. The content type of the response is determined by the HTTP Header field Accept with a value of application/xml or application/json.</p>
<p><a href="http://djna.files.wordpress.com/2009/12/headerjson.jpg"><img title="HeaderJson" style="display:inline;border-width:0;" height="92" alt="HeaderJson" src="http://djna.files.wordpress.com/2009/12/headerjson_thumb.jpg?w=435&#038;h=92" width="435" border="0" /></a> </p>
<h2>Testing from Dojo</h2>
<p>One very likely scenario for using REST services is to call&#160; an operation from an Browser-based rich client application. The Dojo JavaScript libraries are one possible technology for constructing such applications.</p>
<p>This is some sample code which invokes the addNewEdition() operation:</p>
<p>&#160;&#160;&#160;&#160;&#160; var myEdition = {&#34;Edition&#34;:{“author”:”x”, “title”&#34;isbn&#34;:&#34;44&#34;}};    <br />&#160;&#160;&#160;&#160;&#160; var xhrArgs = {     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; url: http://myhost/LibraryWink/library/editions,     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; postData: dojo.toJson(myEdition),     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; handleAs: &#34;json&#34;,     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; headers: { &#34;Content-Type&#34;: &#34;application/json&#34;},     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; load: function(data) {     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; dojo.byId(&#34;mainMessageText&#34;).innerHTML     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; =&#160; &#34;Message posted.&#34;;     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; },     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; error: function(error) {     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; dojo.byId(&#34;mainMessageText&#34;).innerHTML     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; = &#34;Error :&#34; + error;     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; };     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; dojo.byId(&#34;mainMessageText&#34;).innerHTML     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; = &#34;Message being sent&#8230;&#34;;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; var deferred = dojo.rawXhrPost(xhrArgs);</p>
<p>I’ll quickly summarise a few key features here, but first note in particular the actual POST request:</p>
<p>&#160;&#160;&#160; dojo.rawXhrPost(xhrArgs);</p>
<p>You note that I use rawXhrPost rather than</p>
<p>&#160;&#160;&#160; dojo.xhrPost(xhrArgs);</p>
<p>I can find no documentation that explains why rawXhrPost() is needed, but after much experimenting and imprecating I discovered that rawXhrPost() does indeed work and that xhrPost() sends no payload.</p>
<p>The other salient points:</p>
<ul>
<li>postData: dojo.toJson(myEdition) converts the payload object to JSON.</li>
<li>headers: { &#34;Content-Type&#34;: &#34;application/json&#34;} sets the MimeType in the header, hence allowing JAX-RS to correctly interpret the JSO string – the <strong>handleAs</strong> property relates to the interpretation of any response from the service </li>
<li>The url: http://myhost/LibraryWink/library/editions is our resource URI</li>
</ul>
<h3>Next – Unit Testing</h3>
<p>So, that’s two ways of exercising a REST service, however as a test mechanism both leave a few things to be desired. In the next posting I’ll move on to using JAS-RS client</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Possible POE support in Resteasy]]></title>
<link>http://bill.burkecentral.com/2009/12/03/possible-poe-support-in-resteasy/</link>
<pubDate>Thu, 03 Dec 2009 19:31:56 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/12/03/possible-poe-support-in-resteasy/</guid>
<description><![CDATA[I was thinking about some POE support for Resteasy.  On the client side add a poe() set of methods o]]></description>
<content:encoded><![CDATA[I was thinking about some POE support for Resteasy.  On the client side add a poe() set of methods o]]></content:encoded>
</item>
<item>
<title><![CDATA[JAX-RS with Apache Wink]]></title>
<link>http://djna.wordpress.com/2009/12/02/jax-rs-with-apache-wink/</link>
<pubDate>Wed, 02 Dec 2009 15:49:09 +0000</pubDate>
<dc:creator>djna</dc:creator>
<guid>http://djna.wordpress.com/2009/12/02/jax-rs-with-apache-wink/</guid>
<description><![CDATA[JAX-RS is a specification addressing the implementation of providers and consumers of REST services ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>JAX-RS is a specification addressing the implementation of providers and consumers of REST services in Java. Apache Wink is an Open Source implementation of that specification. To give an idea of what is possible: you can annotate a Java Class like this</p>
<p>&#160;&#160;&#160; <font face="Courier New" size="1">@Path(“/books”)      <br />&#160;&#160;&#160; public class LibraryResource {</font></p>
<p><font face="Courier New" size="1">&#160;&#160;&#160; @GET      <br />&#160;&#160;&#160; @Produces( MediaType.APPLICATION_JSON)       <br />&#160;&#160;&#160; public BookCollection getBooks() {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // implementation here</font></p>
<p><font face="Courier New" size="1">&#160;&#160;&#160; }</font></p>
<p>and deploy this class along with the Wink framework to an Application Server and you have immediately implemented a RESTful service with a URI</p>
<p>&#160;&#160;&#160; http://myhost/rest/books</p>
<p>In this posting I will explain in detail how to use Apache Wink to implement a service like this. I will be creating RESTful services for a simplified, fictional Lending library. First, a reminder of the problems addressed by JAX-RS. I’ve described the service providers responsibilities in more detail <a href="http://djna.wordpress.com/2009/12/02/rest-services-the-responsibilities-of-a-service-provider/">in this posting</a> but in summary we first need to do some up-front design work:</p>
<ul>
<li>Identify some resources, in our case these could be Books, Editions, Authors, Categories and Borrowers </li>
<li>Decide on the URIs that identify these resources, both individual resources and collections of resources. </li>
<li>Design the services, giving appropriate meanings to methods such as GET, PUT, POST and DELETE </li>
</ul>
<p>Then we write code and exploit JAX-RS (and JAXB) to address these implementation problems:</p>
<ol>
<li>Transform between the State of a Resource and its Transfer Representation. That is, manage the conversion between a Java Object and an XML or JSON representation of its attributes. </li>
<li>Interpret the URI of a service request and direct the request to the appropriate Resource Manager, which we have developed in Java. </li>
<li>Map the HTTP method (GET, PUT …) to appropriate methods of the Resource Manager. </li>
<li>Enable the resource manager to use the details of the URI to identify particular resources. for example
<p>http://myhost/rest/borrowers/12345       </p>
<p>would identify a borrower with id 12345 </li>
<li>Give access to qualifying parameters such as search criteria </li>
</ol>
<h1></h1>
<h1></h1>
<h1>Preparation</h1>
<p>I am using Rational Application Developer 7.5&#160; (RAD) and the WebSphere Application Server 7.0 (WAS) test environment provided by RAD. I downloaded Apache WINK and then added WINK jar files to my dynamic web project.</p>
<h2>Download Wink</h2>
<p>Apache WINK can be downloaded from <a href="http://incubator.apache.org/wink/downloads.html">Wink Download</a>. I downloaded </p>
<blockquote><p>apache-wink-1.0-incubating.zip</p>
</blockquote>
<p>This contains directories</p>
<ul>
<li>dist &#8211; the core of Wink </li>
<li>lib –&#160; wink supporting libraries </li>
<li>ext/wink-json-provider – JSON formatting and parsing </li>
</ul>
<p>There is also documentation and examples.</p>
<h2>Creating and Populating Web Project</h2>
<p>In RAD create an Application (EAR) project and Dynamic Web Project, then add the Wink JAR files, define the Wink servlet and create packages for the Java Classes we will write shortly. The next sections describe these steps in more detail.</p>
<h3>Wink JAR files</h3>
<p>Copy the following jar files from the Wink distribution to the WEB-INF lib directory of the dynamic web project. </p>
<p>From dist</p>
<blockquote><p>wink-server-1.0-incubating.jar      <br />wink-common-1.0-incubating.jar </p>
</blockquote>
<p>From lib:</p>
<blockquote><p>jsr311-api-1.0.jar      <br />slf4j-api-1.5.8.jar       <br />slf4j-simple-1.5.8.jar </p>
</blockquote>
<p>(note that instead of slf4j-simple-1.5.8.jar you may prefer to use a different slf4j implementation such as slf4j-jdk14-1.5.8.jar, you can download that from <a href="http://www.slf4j.org/download.html">here</a>.</p>
<p>From ext/wink-json-provider </p>
<blockquote><p>lib/json-20080701.jar    <br />wink-json-provider-1.0-incubating.jar </p></blockquote>
<p>So my LibraryEar and LibraryWink projects now look like this</p>
<p><a href="http://djna.files.wordpress.com/2009/12/projectjar1.jpg"><img title="ProjectJar" style="border-right:0;border-top:0;display:inline;border-left:0;border-bottom:0;" height="399" alt="ProjectJar" src="http://djna.files.wordpress.com/2009/12/projectjar_thumb1.jpg?w=266&#038;h=399" width="266" border="0" /></a>&#160;</p>
<h3>Wink Servlet</h3>
<p>Edit WEB-INF/web.xml, add the servlet definition.</p>
<blockquote><p>&#160; <em><strong>&#60;servlet&#62;          <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;servlet-name&#62;restSdkService&#60;/servlet-name&#62;           <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;servlet-class&#62;org.apache.wink.server.internal.servlet.RestServlet&#60;/servlet-class&#62;           <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;init-param&#62;           <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;param-name&#62;applicationConfigLocation&#60;/param-name&#62;           <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;param-value&#62;/WEB-INF/application&#60;/param-value&#62;           <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;/init-param&#62;           <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;load-on-startup&#62;0&#60;/load-on-startup&#62;           <br />&#160;&#160;&#160; &#60;/servlet&#62;</strong></em></p>
<p><em><strong>&#160;&#160;&#160; &#60;servlet-mapping&#62;          <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;servlet-name&#62;restSdkService&#60;/servlet-name&#62;           <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;url-pattern&#62;/library/*&#60;/url-pattern&#62;           <br />&#160;&#160;&#160; &#60;/servlet-mapping&#62;</strong></em></p>
</blockquote>
<p>This has the effect of mapping all URLs begging with “library” to the Wink REST servlet. </p>
<p>The Web project now shows a servlet:</p>
<p><a href="http://djna.files.wordpress.com/2009/12/servlet.jpg"><img title="Servlet" style="display:inline;border-width:0;" height="228" alt="Servlet" src="http://djna.files.wordpress.com/2009/12/servlet_thumb.jpg?w=239&#038;h=228" width="239" border="0" /></a> </p>
<p>We will create our own resource manager classes with JAX-RS annotation that will implement the service function and hook that servlet to call our implementation: note that the servlet has an initialisation parameter applicationConfigLocation which refers to a file</p>
<p>&#160;&#160;&#160; /WEB-INF/application</p>
<p>the purpose of this file is to register our resource manager code with the Wink servlet. We’ll create that file once we have written the code.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </p>
<h3>Creating Packages</h3>
<p>I created two packages to differentiate two kinds of Class used in the service implementation: </p>
<ul>
<li><strong>org.djna.library.service:</strong> the resource manager classes, these being the classes that offer the service interfaces themselves </li>
<li><strong>org.djna.library.resources: </strong>the resource state classes, which hold the data passed to and from the service methods, these classes will be serialised to and from JSON and XML </li>
</ul>
<p><a href="http://djna.files.wordpress.com/2009/12/packages.jpg"><img title="Packages" style="display:inline;border-width:0;" height="109" alt="Packages" src="http://djna.files.wordpress.com/2009/12/packages_thumb.jpg?w=244&#038;h=109" width="244" border="0" /></a> </p>
<p>In the next section I’ll describe how to implement the state and resource manager classes</p>
<h1>Information using JAXB</h1>
<p>I&#160; first create classes to hold the state of the various resources in our system. In this example they will be simple Java Beans with with minimal&#160; business logic, effectively just Data Transfer Objects that will be serialised to and from JSON or XML. Something I want to study in the future is the relationship between these resource objects and JPA Entities.</p>
<h3>Book Edition</h3>
<p>We’ll start with a simple class representing an Edition of a Book. In this simple example the class has few attributes:</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font face="Courier New" size="1">package org.djna.library.resources;</font></p>
<p><font face="Courier New" size="1">&#160;&#160;&#160;&#160; import java.util.Date; </font></p>
<blockquote><p><font face="Courier New" size="1">public class BookEdition {        <br />&#160;&#160;&#160; private String title;         <br />&#160;&#160;&#160; private String author;         <br />&#160;&#160;&#160; private String isbn;         <br />&#160;&#160;&#160; private Date publicationDate;</font></p>
</blockquote>
<p>The isbn uniquely identifies the book edition. </p>
<p>I generated getters and setters for every field, for example</p>
<blockquote><p>&#160;&#160;&#160; <font face="Courier New" size="1">public String getTitle() {        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; return title;&#160; <br />&#160; }&#160; <br />&#160; public void setTitle(String title) {         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; this.title = title;&#160; <br />&#160; }</font></p>
</blockquote>
<p>I also created a two constructors, one takes no arguments and one allowing a fully populated BookEdition to be created. </p>
<blockquote><p><font face="Courier New" size="1">&#160;&#160;&#160; public BookEdition() {        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; title = null;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; author = null;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; isbn = null;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; publicationDate = null;         <br />&#160;&#160;&#160; }         <br />&#160;&#160;&#160;&#160;&#160;&#160; public BookEdition(String nTitle,         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; String nAuthor,         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; String nIsbn,         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Date nPublicationDate){         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; title = nTitle;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; author = nAuthor;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; isbn = nIsbn;         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; publicationDate = nPublicationDate;         <br />&#160;&#160;&#160; }</font></p>
</blockquote>
<p>The zero argument constructor is required by JAXB.</p>
<h3>Annotating for Serialization</h3>
<p>The BookEdition class will be passed to and from the REST service and so must be serializable. This is quickly accomplished by adding annotations to the class.</p>
<blockquote><p><font face="Courier New" size="1">@XmlAccessorType(XmlAccessType.PROPERTY)        <br />@XmlRootElement(name = &#34;Edition&#34;)&#160; <br />public class BookEdition {</font></p>
</blockquote>
<p><font size="1">These two annotations are sufficient to enable BookEdition to be transformed to and from XML and JSON. </font></p>
<ul>
<li><font size="1">The <strong>XmlAccessorType</strong>, with parameter&#160; <strong>XmlAccessType.PROPERTY </strong>specifies that the attributes to be serialised will be deduced from the presence of Getters and Setters in the class. This a very simple use of JAXB. JAXB has many other capabilities, for example by using other XmlAccessTypes you can expose attributes directly. Also, if necessary you can get finer control over which fields are to be serialised and their serialized representations by applying other annotations to individual attributes. </font></li>
<li>XmlRootElement specifies the root element of the XML or JSON payload. </li>
</ul>
<h1>Resources using JAX-RS</h1>
<p>Next I create a Resource Manager which will offer services to manipulate BookEditions and specify a base URI for the services. I then create the individual service methods which act on particular resources and collections of resources. In order to enable testing of the services I create a Mock Data Store for Book Editions which simply works with a few hard-coded examples.</p>
<p>This assumes that I have already made decisions about the URIs I intend to use to access my resources.&#160; For this simple case, with only a single kind of resource the following URIs (I show only the significant portion of the URI, prepend <strong>http://myhost/rest</strong> to all these) will be sufficient:</p>
<ul>
<li><strong>/editions</strong> : all book editions </li>
<li><strong>/editions?query=XXX</strong> : editions matching query </li>
<li><strong>/editions/0858835544</strong> : a particular edition specified by its ISBN </li>
</ul>
<p>In the remainder of this posting I’ll focus on implementing that final operation, the retrieval of an Editions’s state specified by its ISBN.</p>
<h2></h2>
<h3>Resource Manager Class</h3>
<p>JAX-RS has a rich set of capabilities for mapping REST URIs to methods of resoruce manager classes. I&#8217; implemented a very simple case: a single resource manager with methods for each particular operation I wanted to expose.</p>
<h4>Resource Manager Class and Path</h4>
<p>The resource manager class is an an arbitrary class, no special requirements for inheritance or interface implementation. It is annotated&#160; to specify the URIs that will be dispatched to this class</p>
<p>&#160;&#160;&#160; <font face="courier n" size="1">package org.djna.library.service; </font></p>
<p><font face="courier n" size="1">&#160;&#160;&#160; import javax.ws.rs.Path;</font></p>
<p><font face="courier n" size="1">&#160;&#160;&#160; @Path(&#34;/editions&#34;)      <br />&#160;&#160;&#160;&#160; public class BookEditionResources {</font></p>
<p>The context root for the Web Application is <strong>LibraryWink</strong> and the servlet is mapped to <strong>library</strong> hence the base URI for the REST services exposed by this resource manager is</p>
<p>&#160;&#160; <strong>http://myhost/LibraryWink/library/editions</strong></p>
</p>
<p>Next I prepared some example, hard-coded data items.</p>
<h4>Example Data</h4>
<p>The EditionStore class is included in the project ZIP file (TBD).</p>
<h4>Retrieve One Item – GET</h4>
<p>The first method I implemented retrieved a single edition, specified by its ISBN. That is, we implement a GET method for the URI</p>
<p>&#160;&#160; <strong>http://myhost/LibraryWink/library/editions/0858835544</strong> </p>
<p>The method in the resource manager looks like this</p>
<p>&#160;&#160; <strong>@Path(&#34;{isbn}&#34;)      <br />&#160;&#160;&#160; @GET       <br />&#160;&#160;&#160; @Produces( MediaType.APPLICATION_JSON)       <br />&#160;&#160;&#160; public BookEdition getEditionByIsbn(@PathParam(&#34;isbn&#34;) String isbn) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; return EditionStore.getInstance().getEdition(isbn);       <br />&#160;&#160;&#160; }</strong></p>
<p>The JAX-RS runtime has a flexible algorithm for matching the request to the service method, this considers the matching of the request URI to the @PATH annotations for class and method, the HTTP method types (GET, POST …) and also the requested Media Types.&#160; In the general case the algorithm&#160; needs to deal with the possibilities of there being many resource managers each with many methods. There is an explanation of the algorithm <a href="http://cwiki.apache.org/CXF20DOC/jax-rs.html#JAX-RS-Overviewoftheselectionalgorithm.">here</a>.</p>
<p>In this <strong>getEditionByIsbn()</strong> example we see that the method is annotated with <strong>@GET</strong> to indicate that it deals with HTPP GET requests, and with <strong>@Produces( MediaType.APPLICATION_JSON)</strong> to specify that the response is in JSON format. It is possible to specify more than one Media type (for example both XML and JSON) in which case the client may specify its preference.</p>
<p>The @Path(&#34;{isbn}&#34;) annotation is a little more complex. Two things are happening here. First, this Path is used in conjunction with the overall ResouceManager class Path annotation so that the request URI that will be serviced by this method will look like this</p>
<p>&#160;&#160;&#160;&#160; http://myhost/LibraryWink/library/editions/XXXXX</p>
<p>where XXXX will be a specific ISBN. The second thing that is being specified is that the isbn portion of the URI is to be accessible as a parameter, the parameter having the name <strong><u>isbn</u></strong>.</p>
<p>This now gives a context for the final annotation:<strong> @PathParam(&#34;isbn&#34;)</strong> the method declaration </p>
<p>&#160;&#160;&#160; <strong>getEditionByIsbn(@PathParam(&#34;isbn&#34;) String isbn)</strong></p>
<p>specifies that the Java method takes a single String parameter, and the annotation of that parameter tells JAX-RS to populate that parameter from the URI path. </p>
<h5>Application Configuration</h5>
<p>You may remember that we need to configure the Wink REST servlet to use our application code. We do this by creating a simple text file in the location specified by the servlet’s applicationConfigLocation parameter, that is a text fille: WEB_INF/application</p>
<p>The contents of the file is a simple list of resource manager classes, in our case just</p>
<p>&#160;&#160;&#160; org.djna.library.service.BookEditionResources</p>
<h5>Execute</h5>
<p>I can now deploy the code to the WAS test environment and using a browser issue the GET request</p>
<p>&#160; <strong>http://myhost/LibraryWink/library/editions/1900924323</strong></p>
<p>The response is a simple JSON string containing the details of the Edition with ISBN 1900924323</p>
<p>&#160;&#160; <strong>{ &#34;Edition&#34;: {      <br />&#160;&#160;&#160;&#160; &#34;author&#34;: &#34;Brian Hinton, Geoff Wall&#34;,       <br />&#160;&#160;&#160;&#160; &#34;isbn&#34;: &#34;1900924323&#34;,       <br />&#160;&#160;&#160;&#160; &#34;publicationDate&#34;: &#34;2002-03-27T14:45:43.437+00:00&#34;,       <br />&#160;&#160;&#160;&#160; &#34;title&#34;: &#34;The Guvnor&#34;       <br />&#160;&#160; }&#160; }</strong></p>
<h2><strong>Conclusion</strong>&#160;</h2>
<p>The experience of coding a RESTful service using the Apache Wink implementation of JAX-RS is pretty good, I wrote very little code and achieved a working implementation very quickly. There’s a few directions for further study:</p>
<ul>
<li>The relationship between our resource classes and JPA entities. Can we (and should we) annotate a class with both JPA and JAXB annotations?</li>
<li>How easy will it be to implement PUT, POST and DELETE?</li>
<li>How easily can we implement queries across collections?</li>
<li>JAX-RS has various techniques for allowing to refactor resource manager logic, with flexible URI path specifications. Are there obvious patterns for using these capabilities?</li>
<li>JAX-RS enables various life-cycle models for resource managers. How easy are they to use?</li>
</ul>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[REST Services: The Responsibilities of a Service Provider]]></title>
<link>http://djna.wordpress.com/2009/12/02/rest-services-the-responsibilities-of-a-service-provider/</link>
<pubDate>Wed, 02 Dec 2009 15:35:19 +0000</pubDate>
<dc:creator>djna</dc:creator>
<guid>http://djna.wordpress.com/2009/12/02/rest-services-the-responsibilities-of-a-service-provider/</guid>
<description><![CDATA[RESTful services are particularly useful for Web 2.0 developers and are pleasingly easy to develop i]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>RESTful services are particularly useful for Web 2.0 developers and are pleasingly easy to develop in Java using the <a href="http://incubator.apache.org/wink/">Apache Wink</a> implementation of JAX-RS. You can get more detail about REST starting <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">here in Wikipedia</a> in this posting I want to illustrate the significance of&#160; JAX-RS by considering the responsibilities of the a developer who wants to provide a REST service. In a <a href="http://djna.wordpress.com/2009/12/02/jax-rs-with-apache-wink/">more detailed posting</a> I describe in detail how to use Wink to create a few simple services for a Lending Library.</p>
<p><strong>RE</strong>presentation <strong>S</strong>tate <strong>T</strong>ransfer (<strong>REST</strong>) is concerned with the State of resources and passing of representations of that state between client and server. So, we need to understand:</p>
<ul>
<li>what is meant by a <strong>resource</strong> </li>
<li>how <strong>URIs</strong> are used to specify particular <strong>resources</strong> </li>
<li>how requests to retrieve and manipulate the <strong>state</strong> of a resource are defined by the client </li>
<li>the <strong>representation</strong> of the <strong>state</strong> as it is transfered between client and server </li>
</ul>
<h2>Resources</h2>
<p>Resources may be any entity (or collection of entities) owned by a service provider. They are often familiar business entities such as Customers and Orders. I am&#160; library examples we might have Books and DVDs. We also treat collections of entities as resources, for example “All orders placed today” or “Books written by Alastair Reynolds”.</p>
<p>We can easily imagine a simple mapping between records in a Relational Database and the resources managed by a service provider. However we can also treat more abstract information as resources., for example “The temperature now in London” or “The current stock price for IBM on the NYSE”.</p>
<p>So our first task as a REST service provider is to <strong>identify the resources</strong> our service is managing. Typically we will give some detailed consideration as to how clients would like to refer to the resource and that leads to define the URIs by which clients with specify the resources.</p>
<h2>URI</h2>
<p>Strictly speaking REST services can use many different technologies, they are not limited to the use of Web technologies and HTTP protocols, but here I am going to focus on the most common case, accessing resources specified by a URI using HTTP (or HTTPS).</p>
<p>The service provider will define the URIs that specify particular resources. In our library example we might have</p>
<ul>
<li>http://my.library.org/books&#160; which would be a collection of all books </li>
<li>http://my.library.org/books/abc001 which references a particular book using its identifier <strong>abc001</strong> </li>
</ul>
<p>and we can similarly use URIs to specify more abstract information such as</p>
<ul>
<li>http://my.weather.org/current/uk/london/temperature </li>
</ul>
<p>We see here a more extensive URI hierarchy and this indicates the extent of design effort that may be required in the resource identification activity so that we can define the URIs to be used.</p>
<p>This leads to some specific implementation coding tasks:</p>
<ol>
<li>The URI <strong>http://my.library.org/books</strong> must in some way map to code that actually manages the book resources, and similarly the <strong>http://my.weather.org/current</strong> URI must be associated with the resource manager for the current weather resources. </li>
<li>The resource manager must interpret more precise URIs in order to identify the specific resources. So&#160; <strong>uk/london/temperature</strong> must be interpreted correctly, the implementer needs structured access to the URI. </li>
</ol>
<p>The implementation tasks are addressed by JAX-RS, and in the <a href="http://djna.wordpress.com/2009/12/02/jax-rs-with-apache-wink/">more detailed article</a> I describe how to use JSX-RS annotations to complete the service implementation.</p>
<p>These ideas are extended further to allow the passing of parameters in the URI, in the example the collection URI is&#160; modified by some search criteria</p>
<blockquote><p>http://my.library.org/books?author=doyle</p>
</blockquote>
<p>JAX-RS has annotations to allow access to parameters of various kinds.</p>
<h2>Methods</h2>
<p>RESTful architecture using HTTP explicitly exploits of HTTP methods such as <strong>GET, PUT, POST and DELETE</strong>, to define actions on resources:</p>
<ul>
<li>GET: retrieve a representation of the resources specified by the URI </li>
<li>PUT: replace the state of the resource specified by the URI with new values </li>
<li>POST: add a new resource, typically the URI will be that of a collection and the specified ID will be be generated by the resource manager or derived from the payload </li>
<li>DELETE: remove the resource specified by the URI </li>
</ul>
<p>This too leads to specific coding tasks: the implementer needs to map from the HTTP method to the appropriate action.</p>
<h2>Representation</h2>
<p>The resource representation returned from&#160; a GET or (for example) specified in a PUT can be in arbitrary format as specified by the MIME type of the request, usually that type would be application/xml for XML application/json for JSON.</p>
<p>From the service provider’s perspective this leads to two further tasks:</p>
<ol>
<li>To determine the request MIME type </li>
<li>To parse requests or format responses in accordance with that type. </li>
</ol>
<p>JAX-RS has annotation capabilities to deal with different MIME types, however the corresponding&#160; parsing and formatting is not part of the JAX-RS as such, but rather is provided by JAXB, hence we will need to use some JAXB annotations when supporting the chosen MIME types.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[RESTEasy 1.2.1 Released]]></title>
<link>http://bill.burkecentral.com/2009/11/23/resteasy-1-2-1-released/</link>
<pubDate>Mon, 23 Nov 2009 17:32:22 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/11/23/resteasy-1-2-1-released/</guid>
<description><![CDATA[Minor bug fix release.  Also, had to remove one of the referenced maven repositories because it was ]]></description>
<content:encoded><![CDATA[Minor bug fix release.  Also, had to remove one of the referenced maven repositories because it was ]]></content:encoded>
</item>
<item>
<title><![CDATA[RESTEasy 1.2.GA Released]]></title>
<link>http://bill.burkecentral.com/2009/11/04/resteasy-1-2-ga-released/</link>
<pubDate>Wed, 04 Nov 2009 15:34:58 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/11/04/resteasy-1-2-ga-released/</guid>
<description><![CDATA[After a few months RESTEasy 1.2.GA is finally ready.  This is mostly a cleanup, bug fix, and refacto]]></description>
<content:encoded><![CDATA[After a few months RESTEasy 1.2.GA is finally ready.  This is mostly a cleanup, bug fix, and refacto]]></content:encoded>
</item>
<item>
<title><![CDATA[RESTful Web Services the easy way with JAX-RS]]></title>
<link>http://bjarlestam.wordpress.com/2009/09/15/introduction-to-jax-rs/</link>
<pubDate>Tue, 15 Sep 2009 06:36:33 +0000</pubDate>
<dc:creator>bjarlestam</dc:creator>
<guid>http://bjarlestam.wordpress.com/2009/09/15/introduction-to-jax-rs/</guid>
<description><![CDATA[Here are the slides that I have prepared for my talk at JavaForum this evening. It took me some time]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Here are the slides that I have prepared for my talk at <a href="http://www.javaforum.se">JavaForum</a> this evening. It took me some time to cut it down to 34 slides and then still many of them had to become extra spare slides. I had to realize that 30 minutes is really not much time. On the other hand I&#8217;ve seen many 10 minute lightning talks where the speaker manages to deliver the essence of a pretty complicated topic, so I shouldn&#8217;t really complain.</p>
<p><!-- SlideShare error: doc is missing or has illegal characters /[^-_a-zA-Z0-9]/ --></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Globalcode's Casual Class: JAVAEE 6]]></title>
<link>http://jcranky.wordpress.com/2009/09/06/globalcodes-casual-class-javaee-6/</link>
<pubDate>Sun, 06 Sep 2009 22:52:51 +0000</pubDate>
<dc:creator>Paulo Renato</dc:creator>
<guid>http://jcranky.wordpress.com/2009/09/06/globalcodes-casual-class-javaee-6/</guid>
<description><![CDATA[This is a little late, but anyway&#8230; Two weeks ago I attend one more of the Globalcode&#8217;s C]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>This is a little late, but anyway&#8230;</p>
<p>Two weeks ago I attend one more of the <a title="Globalcode" href="http://www.globalcode.com.br" target="_blank">Globalcode</a>&#8217;s <a title="Casual Class" href="http://www.casualclass.com.br/" target="_blank">Casual Class</a>&#8216;es. This one was about JAVAEE 6 and the main technologies that will be part of it when it comes out &#8211; apparently very soon.</p>
<p>I don&#8217;t have many pictures because I&#8217;m very smart and let my mobile&#8217;s battery run out&#8230; but let&#8217;s go through a few of the ones I got and talk about the contents of this event.</p>
<div id="attachment_371" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-371" title="Preparations" src="http://jcranky.wordpress.com/files/2009/09/28082009650.jpg?w=300" alt="Preparations" width="300" height="225" /><p class="wp-caption-text">Preparations</p></div>
<p>The event was split in a few individual topics, among them: JSF 2.0, JAX-RS, EJB 3.1 and JPA 2.0. Each one had different presenters, all of them great speakers! =)</p>
<div id="attachment_372" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-372" title="JSF 2.0" src="http://jcranky.wordpress.com/files/2009/09/28082009651.jpg?w=300" alt="JSF 2.0" width="300" height="225" /><p class="wp-caption-text">JSF 2.0</p></div>
<p>JSF 2.0 was presented by Yara Senger and Alberto &#8220;Spock&#8221; Lemos. They mentioned some changes that are coming to JSF, and used a small demo application, SCRUM Toys, to explain how they got involved into actually using the new features.</p>
<div id="attachment_373" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-373" title="JPA 2.0" src="http://jcranky.wordpress.com/files/2009/09/28082009654.jpg?w=300" alt="JPA 2.0" width="300" height="225" /><p class="wp-caption-text">JPA 2.0</p></div>
<p>Melissa Vilela spoke about the new features coming in JPA 2.0. There are a lot of nice things. Among them, the new Criteria API <strong>is not</strong>. To be brutally honest, that thing is ridiculously complex. It is clearly lacking some usage of the <a title="KISS Principle" href="http://en.wikipedia.org/wiki/Keep_it_simple_stupid" target="_blank">KISS</a> principle.</p>
<p>Then there was a presentation about REST, more specifically JAX-RS. (no pictures, sorry). Nothing really new here, just the fact that the API, which was already done and available, is going to be part of JAVAEE 6.</p>
<div id="attachment_374" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-374" title="EJB 3.1" src="http://jcranky.wordpress.com/files/2009/09/28082009655.jpg?w=300" alt="EJB 3.1" width="300" height="225" /><p class="wp-caption-text">EJB 3.1</p></div>
<p>The last topic was EJB 3.1. Like with EJB 3.0, things are moving towards a simpler development model, and this is what was presented. Nice, simplifications to EJBs are always welcome! =)</p>
<p>After that, Pizza! uhu! My only complain this time is that the technical sessions took longer than usual, and I was really hungry in the end! But it was well worth the time =)</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Yet another reason to avoid Apache.org]]></title>
<link>http://bill.burkecentral.com/2009/08/29/yet-another-reason-to-avoid-apache-org/</link>
<pubDate>Sat, 29 Aug 2009 14:28:09 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/08/29/yet-another-reason-to-avoid-apache-org/</guid>
<description><![CDATA[I find  it strange how Apache.org allows for competing projects as they don&#8217;t really position ]]></description>
<content:encoded><![CDATA[I find  it strange how Apache.org allows for competing projects as they don&#8217;t really position ]]></content:encoded>
</item>
<item>
<title><![CDATA[Using JSP with Jersey JAX-RS Implementation]]></title>
<link>http://blog.docuverse.com/2009/08/04/using-jsp-with-jersey-jax-rs-implementation/</link>
<pubDate>Wed, 05 Aug 2009 06:21:08 +0000</pubDate>
<dc:creator>donpark</dc:creator>
<guid>http://blog.docuverse.com/2009/08/04/using-jsp-with-jersey-jax-rs-implementation/</guid>
<description><![CDATA[This post shows you some tips you&#8217;ll likely need to use JSP with Jersey in typical Java webapp]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>This post shows you some tips you&#8217;ll likely need to use JSP with Jersey in typical Java webapps.</p>
<p><em>Tested Conditions</em></p>
<p>While Jersey 1.1.1-ea or later is probably the only hard requirement for the tips to work, my development environment is listed here for your info. You are welcome to add to this rather meager basis for sanity.</p>
<ol>
<li>Jersey 1.1.1-ea</li>
<li>Tomcat 6.0.20</li>
<li>JDK 1.5</li>
<li>OS X Leopard</li>
</ol>
<p><strong>Change JSP Base Template Path</strong></p>
<p>Default base path for templates is the root of the webapp. So if my webapp is at &#8220;/&#8230;/webapps/myapp&#8221; then Viewable(&#8220;/mypage&#8221;, null) will map to &#8220;/&#8230;/webapps/myapp/mypage.jsp&#8221;</p>
<p>To change this, say to &#8220;WEB-INF/jsp&#8221; as it&#8217;s commonly done for security reasons, add following init-param to Jersey servlet/filter in web.xml:</p>
<pre>&#60;init-param&#62;
&#60;param-name&#62;com.sun.jersey.config.property.JSPTemplatesBasePath&#60;/param-name&#62;
&#60;param-value&#62;/WEB-INF/jsp&#60;/param-value&#62;
&#60;/init-param&#62;</pre>
<p><strong>Return Viewable as part of Response</strong></p>
<p>It was not obvious to me (doh) where Viewable fits into Response when I have to return a Response instead of Viewable. It turns out, Viewable can be passed where message body entity is passed. Example:</p>
<pre>return Response.ok(new Viewable("/mypage", model).build();</pre>
<p><strong>Use &#8220;/*&#8221; as servlet-mapping for Jersey</strong></p>
<p>The primitive servlet-mapping URI pattern scheme, which somehow survived many iterations of the servlet API, impacts JAX-RS hard if servlet-mapping is overly broad. Unfortunately, pretty restful URL calls for servlet-mapping to be &#8220;/*&#8221; instead of something like &#8220;/jersey/*&#8221;, breaking access to JSP files as well as static resources.</p>
<p>To work around, you&#8217;ll have to use Jersey as a filter instead of a servlet and edit a regular-expression init-param value to punch passthrough holes in Jersey&#8217;s routing scheme. To enable this, replace Jersey servlet entry in web.xml with something like this:</p>
<pre>&#60;filter&#62;
 &#60;filter-name&#62;jersey&#60;/filter-name&#62;
 &#60;filter-class&#62;com.sun.jersey.spi.container.servlet.ServletContainer&#60;/filter-class&#62;
 &#60;init-param&#62;
  &#60;param-name&#62;com.sun.jersey.config.property.WebPageContentRegex&#60;/param-name&#62;
  &#60;param-value&#62;/(images&#124;js&#124;styles&#124;(WEB-INF/jsp))/.*&#60;/param-value&#62;
 &#60;/init-param&#62;
&#60;/filter&#62;
&#60;filter-mapping&#62;
 &#60;filter-name&#62;jersey&#60;/filter-name&#62;
 &#60;url-pattern&#62;/*&#60;/url-pattern&#62;
&#60;/filter-mapping&#62;</pre>
<p>That&#8217;s all for now. Hope this post saved you some headaches.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Writing a Last.FM REST client with Jersey and Java-Gnome]]></title>
<link>http://skaba.wordpress.com/2009/07/26/writing-a-last-fm-rest-client-with-jersey-and-java-gnome/</link>
<pubDate>Sun, 26 Jul 2009 08:50:49 +0000</pubDate>
<dc:creator>Serkan Kaba</dc:creator>
<guid>http://skaba.wordpress.com/2009/07/26/writing-a-last-fm-rest-client-with-jersey-and-java-gnome/</guid>
<description><![CDATA[This tutorial will start with a sample top artists (i.e favorite artists) file from http://ws.audios]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>This tutorial will start with a sample top artists (i.e favorite artists) file from <a href="http://ws.audioscrobbler.com/2.0/?method=user.gettopartists&#38;user=Firari&#38;api_key=b25b959554ed76058ac220b7b2e0a026" target="_blank">http://ws.audioscrobbler.com/2.0/?method=user.gettopartists&#38;user=Firari&#38;api_key=b25b959554ed76058ac220b7b2e0a026</a>. It will follow several steps to write a dynamic client GTK UI for the topartists service. Project depends on java-gnome (4.0.12+), jsr311-api (aka jax-rs), jersey-core and jersey-client libraries. Note that there&#8217;s a Java library for accessing Last.FM web services available at <a href="http://www.u-mass.de/lastfm" target="_blank">http://www.u-mass.de/lastfm</a> Project files can be downloaded as a <a href="http://dev.gentoo.org/~serkan/TopArtists.tar.gz">tarball</a>.</p>
<p><strong>Step 1: Generating XML schema from the sample XML</strong></p>
<p>I downloaded a sample file from the the given URL. I used <a href="http://thaiopensource.com/relaxng/trang.html" target="_blank">Trang</a> to reverse engineer the XSD from XML. The command line tool just takes 2 arguments, the input xml and the output xsd files. Here&#8217;s the generated XSD file.</p>
<pre><tt><strong><span style="color:#000080;">&#60;?xml</span></strong> <span style="color:#009900;">version</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"1.0"</span> <span style="color:#009900;">encoding</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"UTF-8"</span><strong><span style="color:#000080;">?&#62;</span></strong>
<strong><span style="color:#0000ff;">&#60;xs:schema</span></strong> <span style="color:#009900;">xmlns:xs</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"http://www.w3.org/2001/XMLSchema"</span> <span style="color:#009900;">elementFormDefault</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"qualified"</span><strong><span style="color:#0000ff;">&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"lfm"</span><strong><span style="color:#0000ff;">&#62;</span></strong>
    <strong><span style="color:#0000ff;">&#60;xs:complexType&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;xs:sequence&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">ref</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"topartists"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;/xs:sequence&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;xs:attribute</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"status"</span> <span style="color:#009900;">use</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"required"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:NCName"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
    <strong><span style="color:#0000ff;">&#60;/xs:complexType&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;/xs:element&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"topartists"</span><strong><span style="color:#0000ff;">&#62;</span></strong>
    <strong><span style="color:#0000ff;">&#60;xs:complexType&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;xs:sequence&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">maxOccurs</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"unbounded"</span> <span style="color:#009900;">ref</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"artist"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;/xs:sequence&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;xs:attribute</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"type"</span> <span style="color:#009900;">use</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"required"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:NCName"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;xs:attribute</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"user"</span> <span style="color:#009900;">use</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"required"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:NCName"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
    <strong><span style="color:#0000ff;">&#60;/xs:complexType&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;/xs:element&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"artist"</span><strong><span style="color:#0000ff;">&#62;</span></strong>
    <strong><span style="color:#0000ff;">&#60;xs:complexType&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;xs:sequence&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">ref</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"name"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">ref</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"playcount"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">ref</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"mbid"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">ref</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"url"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">ref</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"streamable"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">maxOccurs</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"unbounded"</span> <span style="color:#009900;">ref</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"image"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;/xs:sequence&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;xs:attribute</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"rank"</span> <span style="color:#009900;">use</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"required"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:integer"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
    <strong><span style="color:#0000ff;">&#60;/xs:complexType&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;/xs:element&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"name"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:string"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"playcount"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:integer"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"mbid"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:string"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"url"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:anyURI"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"streamable"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:integer"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;xs:element</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"image"</span><strong><span style="color:#0000ff;">&#62;</span></strong>
    <strong><span style="color:#0000ff;">&#60;xs:complexType&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;xs:simpleContent&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;xs:extension</span></strong> <span style="color:#009900;">base</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:anyURI"</span><strong><span style="color:#0000ff;">&#62;</span></strong>
          <strong><span style="color:#0000ff;">&#60;xs:attribute</span></strong> <span style="color:#009900;">name</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"size"</span> <span style="color:#009900;">use</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"required"</span> <span style="color:#009900;">type</span><span style="color:#990000;">=</span><span style="color:#ff0000;">"xs:NCName"</span><strong><span style="color:#0000ff;">/&#62;</span></strong>
        <strong><span style="color:#0000ff;">&#60;/xs:extension&#62;</span></strong>
      <strong><span style="color:#0000ff;">&#60;/xs:simpleContent&#62;</span></strong>
    <strong><span style="color:#0000ff;">&#60;/xs:complexType&#62;</span></strong>
  <strong><span style="color:#0000ff;">&#60;/xs:element&#62;</span></strong>
<strong><span style="color:#0000ff;">&#60;/xs:schema&#62;</span></strong>
</tt></pre>
<p><strong>Step 2: Generating data classes for mapping the xml</strong></p>
<p>xjc (JAXB Binding Compiler) is used to generate the classes in generated package. Jersey can utilize JAXB to map the result XML to data classes.</p>
<p><strong>Step 3: Writing code to query Last.FM web service</strong></p>
<pre><tt><strong><span style="color:#0000ff;">public</span></strong> <strong><span style="color:#0000ff;">static</span></strong> Lfm <strong><span style="color:#000000;">queryTopArtists</span></strong><span style="color:#990000;">(</span>String userName<span style="color:#990000;">)</span> <span style="color:#ff0000;">{</span>
	<strong><span style="color:#0000ff;">final</span></strong> Client client<span style="color:#990000;">;</span>
	<strong><span style="color:#0000ff;">final</span></strong> WebResource webResource<span style="color:#990000;">;</span>
	<strong><span style="color:#0000ff;">final</span></strong> MultivaluedMap queryParams<span style="color:#990000;">;</span>
	<strong><span style="color:#0000ff;">final</span></strong> Lfm result<span style="color:#990000;">;</span>

	client <span style="color:#990000;">=</span> Client<span style="color:#990000;">.</span><strong><span style="color:#000000;">create</span></strong><span style="color:#990000;">();</span>
	webResource <span style="color:#990000;">=</span> client<span style="color:#990000;">.</span><strong><span style="color:#000000;">resource</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"http://ws.audioscrobbler.com/2.0"</span><span style="color:#990000;">);</span>
	queryParams <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">MultivaluedMapImpl</span></strong><span style="color:#990000;">();</span>
	queryParams<span style="color:#990000;">.</span><strong><span style="color:#000000;">add</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"method"</span><span style="color:#990000;">,</span> <span style="color:#ff0000;">"user.gettopartists"</span><span style="color:#990000;">);</span>
	queryParams<span style="color:#990000;">.</span><strong><span style="color:#000000;">add</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"user"</span><span style="color:#990000;">,</span> userName<span style="color:#990000;">);</span>
	queryParams<span style="color:#990000;">.</span><strong><span style="color:#000000;">add</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"api_key"</span><span style="color:#990000;">,</span> <span style="color:#ff0000;">"b25b959554ed76058ac220b7b2e0a026"</span><span style="color:#990000;">);</span>
	result <span style="color:#990000;">=</span> webResource<span style="color:#990000;">.</span><strong><span style="color:#000000;">queryParams</span></strong><span style="color:#990000;">(</span>queryParams<span style="color:#990000;">).</span><strong><span style="color:#000000;">get</span></strong><span style="color:#990000;">(</span>Lfm<span style="color:#990000;">.</span><strong><span style="color:#0000ff;">class</span></strong><span style="color:#990000;">);</span>
	<strong><span style="color:#0000ff;">return</span></strong> result<span style="color:#990000;">;</span>
<span style="color:#ff0000;">}</span>
</tt></pre>
<p>Here we&#8217;re building the HTTP request along with the parameters in the query string. And finally we&#8217;re calling the service and mapping the result to <code>Lfm</code> class which corresponds to XML&#8217;s root element <code>lfm</code>.</p>
<p><strong>Step 4: The GTK+ GUI</strong></p>
<p>Here were initializing the table and its data model.</p>
<pre><tt>
<em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;"> * Initialize the table with its DataColumn's.</span></em>
<em><span style="color:#9a1900;"> */</span></em>
model <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">ListStore</span></strong><span style="color:#990000;">(</span><strong><span style="color:#0000ff;">new</span></strong> DataColumn<span style="color:#990000;">[]</span> <span style="color:#ff0000;">{</span> rank <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">DataColumnString</span></strong><span style="color:#990000;">(),</span>
		artistImage <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">DataColumnPixbuf</span></strong><span style="color:#990000;">(),</span>
		artist <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">DataColumnString</span></strong><span style="color:#990000;">(),</span>
		playCount <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">DataColumnString</span></strong><span style="color:#990000;">(),</span>
		percent <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">DataColumnInteger</span></strong><span style="color:#990000;">()</span> <span style="color:#ff0000;">}</span><span style="color:#990000;">);</span>
view <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">TreeView</span></strong><span style="color:#990000;">(</span>model<span style="color:#990000;">);</span></tt></pre>
<p>Here we&#8217;re creating the view columns and binding their properties to data model. Note that were&#8217;re binding 2 properties of the <code>CellRendererProgress</code> to different columns in the data model.</p>
<pre><tt><em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;"> * Create TreeViewColumns and bind the DataColumn's to their properties.</span></em>
<em><span style="color:#9a1900;"> */</span></em>
vertical <span style="color:#990000;">=</span> view<span style="color:#990000;">.</span><strong><span style="color:#000000;">appendColumn</span></strong><span style="color:#990000;">();</span>
vertical<span style="color:#990000;">.</span><strong><span style="color:#000000;">setTitle</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"Rank"</span><span style="color:#990000;">);</span>
rendererText <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">CellRendererText</span></strong><span style="color:#990000;">(</span>vertical<span style="color:#990000;">);</span>
rendererText<span style="color:#990000;">.</span><strong><span style="color:#000000;">setText</span></strong><span style="color:#990000;">(</span>rank<span style="color:#990000;">);

</span>vertical <span style="color:#990000;">=</span> view<span style="color:#990000;">.</span><strong><span style="color:#000000;">appendColumn</span></strong><span style="color:#990000;">();</span>
rendererPixbuf <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">CellRendererPixbuf</span></strong><span style="color:#990000;">(</span>vertical<span style="color:#990000;">);</span>
rendererPixbuf<span style="color:#990000;">.</span><strong><span style="color:#000000;">setPixbuf</span></strong><span style="color:#990000;">(</span>artistImage<span style="color:#990000;">);</span>

vertical <span style="color:#990000;">=</span> view<span style="color:#990000;">.</span><strong><span style="color:#000000;">appendColumn</span></strong><span style="color:#990000;">();</span>
vertical<span style="color:#990000;">.</span><strong><span style="color:#000000;">setTitle</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"Artist"</span><span style="color:#990000;">);</span>
rendererText <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">CellRendererText</span></strong><span style="color:#990000;">(</span>vertical<span style="color:#990000;">);</span>
rendererText<span style="color:#990000;">.</span><strong><span style="color:#000000;">setText</span></strong><span style="color:#990000;">(</span>artist<span style="color:#990000;">);</span>

vertical <span style="color:#990000;">=</span> view<span style="color:#990000;">.</span><strong><span style="color:#000000;">appendColumn</span></strong><span style="color:#990000;">();</span>
vertical<span style="color:#990000;">.</span><strong><span style="color:#000000;">setTitle</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"# of times played"</span><span style="color:#990000;">);</span>
rendererProgress <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">CellRendererProgress</span></strong><span style="color:#990000;">(</span>vertical<span style="color:#990000;">);</span>
<em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;"> * It's nice that in GTK+ we can bind multiple DataColumn's to</span></em>
<em><span style="color:#9a1900;"> * properties of a single TreeViewColumn.</span></em>
<em><span style="color:#9a1900;"> */</span></em>
rendererProgress<span style="color:#990000;">.</span><strong><span style="color:#000000;">setText</span></strong><span style="color:#990000;">(</span>playCount<span style="color:#990000;">);</span>
rendererProgress<span style="color:#990000;">.</span><strong><span style="color:#000000;">setValue</span></strong><span style="color:#990000;">(</span>percent<span style="color:#990000;">);</span></tt></pre>
<p>Here we&#8217;re querying the service (i.e calling the utility method we wrote) and populating the table. The image data will be fetched asynchroniously by <code>AsyncImageLoader</code> which is a subclass of <code>Thread</code> (Its code wil follow)</p>
<pre><tt><em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;"> * Query Last.FM user.gettopartists method JAX-RS handles the Webservice</span></em>
<em><span style="color:#9a1900;"> * call and JAXB handles the unmarshalling of the XML response.</span></em>
<em><span style="color:#9a1900;"> */</span></em>
result <span style="color:#990000;">=</span> LastFMUtil<span style="color:#990000;">.</span><strong><span style="color:#000000;">queryTopArtists</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"Firari"</span><span style="color:#990000;">);</span>

<em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;"> * Add the properties of Artist items as TreeView rows.</span></em>
<em><span style="color:#9a1900;"> */</span></em>
<strong><span style="color:#0000ff;">if</span></strong> <span style="color:#990000;">(</span>result<span style="color:#990000;">.</span><strong><span style="color:#000000;">getStatus</span></strong><span style="color:#990000;">().</span><strong><span style="color:#000000;">equals</span></strong><span style="color:#990000;">(</span><span style="color:#ff0000;">"ok"</span><span style="color:#990000;">))</span> <span style="color:#ff0000;">{</span>
	<strong><span style="color:#0000ff;">final</span></strong> List<span style="color:#990000;">&#60;</span>Artist<span style="color:#990000;">&#62;</span> topArtists <span style="color:#990000;">=</span> result<span style="color:#990000;">.</span><strong><span style="color:#000000;">getTopartists</span></strong><span style="color:#990000;">().</span><strong><span style="color:#000000;">getArtist</span></strong><span style="color:#990000;">();</span>
	<em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;">	 * Determining maximum playcount from top of the list.</span></em>
<em><span style="color:#9a1900;">	 * It will be used to calculate the percentage of the ProgressBar's.</span></em>
<em><span style="color:#9a1900;">	 */</span></em>
	maxPlayCount <span style="color:#990000;">=</span> topArtists<span style="color:#990000;">.</span><strong><span style="color:#000000;">get</span></strong><span style="color:#990000;">(</span><span style="color:#993399;">0</span><span style="color:#990000;">).</span><strong><span style="color:#000000;">getPlaycount</span></strong><span style="color:#990000;">().</span><strong><span style="color:#000000;">floatValue</span></strong><span style="color:#990000;">();</span>
	<strong><span style="color:#0000ff;">for</span></strong> <span style="color:#990000;">(</span><strong><span style="color:#0000ff;">final</span></strong> Artist artistItem <span style="color:#990000;">:</span> topArtists<span style="color:#990000;">)</span> <span style="color:#ff0000;">{</span>
		<strong><span style="color:#0000ff;">final</span></strong> TreeIter row <span style="color:#990000;">=</span> model<span style="color:#990000;">.</span><strong><span style="color:#000000;">appendRow</span></strong><span style="color:#990000;">();</span>
		model<span style="color:#990000;">.</span><strong><span style="color:#000000;">setValue</span></strong><span style="color:#990000;">(</span>row<span style="color:#990000;">,</span> rank<span style="color:#990000;">,</span> artistItem<span style="color:#990000;">.</span><strong><span style="color:#000000;">getRank</span></strong><span style="color:#990000;">().</span><strong><span style="color:#000000;">toString</span></strong><span style="color:#990000;">());</span>
		<em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;">		 * Asynchronously load the image data and set it as the image</span></em>
<em><span style="color:#9a1900;">		 * column. The first image URL is the "small" one.</span></em>
<em><span style="color:#9a1900;">		 */</span></em>
		<strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">AsyncImageLoader</span></strong><span style="color:#990000;">(</span>model<span style="color:#990000;">,</span> row<span style="color:#990000;">,</span> artistImage<span style="color:#990000;">,</span> artistItem<span style="color:#990000;">.</span><strong><span style="color:#000000;">getImage</span></strong><span style="color:#990000;">().</span><strong><span style="color:#000000;">get</span></strong><span style="color:#990000;">(</span><span style="color:#993399;">0</span><span style="color:#990000;">).</span><strong><span style="color:#000000;">getValue</span></strong><span style="color:#990000;">()).</span><strong><span style="color:#000000;">start</span></strong><span style="color:#990000;">();</span>
		model<span style="color:#990000;">.</span><strong><span style="color:#000000;">setValue</span></strong><span style="color:#990000;">(</span>row<span style="color:#990000;">,</span> artist<span style="color:#990000;">,</span> artistItem<span style="color:#990000;">.</span><strong><span style="color:#000000;">getName</span></strong><span style="color:#990000;">());</span>
		model<span style="color:#990000;">.</span><strong><span style="color:#000000;">setValue</span></strong><span style="color:#990000;">(</span>row<span style="color:#990000;">,</span> playCount<span style="color:#990000;">,</span> artistItem<span style="color:#990000;">.</span><strong><span style="color:#000000;">getPlaycount</span></strong><span style="color:#990000;">().</span><strong><span style="color:#000000;">toString</span></strong><span style="color:#990000;">());</span>
		model<span style="color:#990000;">.</span><strong><span style="color:#000000;">setValue</span></strong><span style="color:#990000;">(</span>row<span style="color:#990000;">,</span> percent<span style="color:#990000;">,</span> Math<span style="color:#990000;">.</span><strong><span style="color:#000000;">round</span></strong><span style="color:#990000;">(</span>artistItem<span style="color:#990000;">.</span><strong><span style="color:#000000;">getPlaycount</span></strong><span style="color:#990000;">().</span><strong><span style="color:#000000;">intValue</span></strong><span style="color:#990000;">()</span> <span style="color:#990000;">/</span> maxPlayCount <span style="color:#990000;">*</span> <span style="color:#993399;">100</span><span style="color:#990000;">));</span>
	<span style="color:#ff0000;">}</span>
<span style="color:#ff0000;">}</span>
</tt></pre>
<p>Here&#8217;s the code for <code>AsyncImageLoader</code>.</p>
<pre><tt><strong><span style="color:#0000ff;">class</span></strong> <span style="color:#009900;">AsyncImageLoader</span> <strong><span style="color:#0000ff;">extends</span></strong> Thread <span style="color:#ff0000;">{</span>
	<strong><span style="color:#0000ff;">private</span></strong> ListStore model<span style="color:#990000;">;</span>
	<strong><span style="color:#0000ff;">private</span></strong> TreeIter row<span style="color:#990000;">;</span>
	<strong><span style="color:#0000ff;">private</span></strong> DataColumnPixbuf artistImage<span style="color:#990000;">;</span>
	<strong><span style="color:#0000ff;">private</span></strong> String url<span style="color:#990000;">;</span>

	<strong><span style="color:#0000ff;">public</span></strong> <strong><span style="color:#000000;">AsyncImageLoader</span></strong><span style="color:#990000;">(</span>ListStore model<span style="color:#990000;">,</span> TreeIter row<span style="color:#990000;">,</span>
			DataColumnPixbuf artistImage<span style="color:#990000;">,</span> String url<span style="color:#990000;">)</span> <span style="color:#ff0000;">{</span>
		<strong><span style="color:#0000ff;">super</span></strong><span style="color:#990000;">();</span>
		<strong><span style="color:#0000ff;">this</span></strong><span style="color:#990000;">.</span>model <span style="color:#990000;">=</span> model<span style="color:#990000;">;</span>
		<strong><span style="color:#0000ff;">this</span></strong><span style="color:#990000;">.</span>row <span style="color:#990000;">=</span> row<span style="color:#990000;">;</span>
		<strong><span style="color:#0000ff;">this</span></strong><span style="color:#990000;">.</span>artistImage <span style="color:#990000;">=</span> artistImage<span style="color:#990000;">;</span>
		<strong><span style="color:#0000ff;">this</span></strong><span style="color:#990000;">.</span>url <span style="color:#990000;">=</span> url<span style="color:#990000;">;</span>
	<span style="color:#ff0000;">}</span>

	@Override
	<strong><span style="color:#0000ff;">public</span></strong> <span style="color:#009900;">void</span> <strong><span style="color:#000000;">run</span></strong><span style="color:#990000;">()</span> <span style="color:#ff0000;">{</span>
		<strong><span style="color:#0000ff;">try</span></strong> <span style="color:#ff0000;">{</span>
			<em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;">			 * Fetch the image data and set it as the image column of the</span></em>
<em><span style="color:#9a1900;">			 * specified row.</span></em>
<em><span style="color:#9a1900;">			 */</span></em>
			URL artistImageURL <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">URL</span></strong><span style="color:#990000;">(</span>url<span style="color:#990000;">);</span>
			URLConnection artistImageConnection <span style="color:#990000;">=</span> artistImageURL
					<span style="color:#990000;">.</span><strong><span style="color:#000000;">openConnection</span></strong><span style="color:#990000;">();</span>
			DataInputStream in <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">DataInputStream</span></strong><span style="color:#990000;">(</span>artistImageConnection
					<span style="color:#990000;">.</span><strong><span style="color:#000000;">getInputStream</span></strong><span style="color:#990000;">());</span>
			<span style="color:#009900;">byte</span><span style="color:#990000;">[]</span> artistImageData <span style="color:#990000;">=</span> <strong><span style="color:#0000ff;">new</span></strong> <span style="color:#009900;">byte</span><span style="color:#990000;">[</span>artistImageConnection
					<span style="color:#990000;">.</span><strong><span style="color:#000000;">getContentLength</span></strong><span style="color:#990000;">()];</span>
			in<span style="color:#990000;">.</span><strong><span style="color:#000000;">readFully</span></strong><span style="color:#990000;">(</span>artistImageData<span style="color:#990000;">);</span>
			<em><span style="color:#9a1900;">/*</span></em>
<em><span style="color:#9a1900;">			 * The image will have 32 pixels height.</span></em>
<em><span style="color:#9a1900;">			 */</span></em>
			model<span style="color:#990000;">.</span><strong><span style="color:#000000;">setValue</span></strong><span style="color:#990000;">(</span>row<span style="color:#990000;">,</span> artistImage<span style="color:#990000;">,</span> <strong><span style="color:#0000ff;">new</span></strong> <strong><span style="color:#000000;">Pixbuf</span></strong><span style="color:#990000;">(</span>artistImageData<span style="color:#990000;">,</span> <span style="color:#993399;">-1</span><span style="color:#990000;">,</span>
					<span style="color:#993399;">32</span><span style="color:#990000;">,</span> <strong><span style="color:#0000ff;">true</span></strong><span style="color:#990000;">));</span>
		<span style="color:#ff0000;">}</span> <strong><span style="color:#0000ff;">catch</span></strong> <span style="color:#990000;">(</span>IOException e<span style="color:#990000;">)</span> <span style="color:#ff0000;">{</span>
			e<span style="color:#990000;">.</span><strong><span style="color:#000000;">printStackTrace</span></strong><span style="color:#990000;">();</span>
		<span style="color:#ff0000;">}</span>
	<span style="color:#ff0000;">}</span>
<span style="color:#ff0000;">}</span>
</tt></pre>
<p>Here&#8217;s a screenshot of the running application.</p>
<p><img class="alignleft size-full wp-image-32" title="TopArtists" src="http://skaba.wordpress.com/files/2009/07/topartists1.png" alt="TopArtists" width="406" height="424" /></p>
<div id="_mcePaste" style="overflow:hidden;position:absolute;left:-10000px;top:3420px;width:1px;height:1px;">The image will have 32 pixels height.</div>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[JAX-RS Javadoc support]]></title>
<link>http://bill.burkecentral.com/2009/07/09/jax-rs-javadoc-support/</link>
<pubDate>Thu, 09 Jul 2009 14:18:32 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/07/09/jax-rs-javadoc-support/</guid>
<description><![CDATA[Stef Epardaud has put together a nice framework that can write Javadocs for you with a JAX-RS spin. ]]></description>
<content:encoded><![CDATA[Stef Epardaud has put together a nice framework that can write Javadocs for you with a JAX-RS spin. ]]></content:encoded>
</item>
<item>
<title><![CDATA[REST presentation]]></title>
<link>http://bjarlestam.wordpress.com/2009/06/16/rest-presentation/</link>
<pubDate>Tue, 16 Jun 2009 12:45:27 +0000</pubDate>
<dc:creator>bjarlestam</dc:creator>
<guid>http://bjarlestam.wordpress.com/2009/06/16/rest-presentation/</guid>
<description><![CDATA[I have put together some slides about the basic principles in REST. The real presentation is actuall]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I have put together some slides about the basic principles in REST. The real presentation is actually implemented as a JAX-RS application. I started out with a django version, but I needed a Java-angle on it so I had to switch to JAX-RS.</p>
<p><!-- SlideShare error: doc is missing or has illegal characters /[^-_a-zA-Z0-9]/ --></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Building GWT web clients [Part 3] &ndash; How to connect GWT client to JAX-RS Jersey server?]]></title>
<link>http://igorshare.wordpress.com/2009/06/08/building-gwt-web-clients-part-3-how-to-connect-gwt-client-to-jax-rs-jersey-server/</link>
<pubDate>Mon, 08 Jun 2009 20:15:23 +0000</pubDate>
<dc:creator>igormoochnick</dc:creator>
<guid>http://igorshare.wordpress.com/2009/06/08/building-gwt-web-clients-part-3-how-to-connect-gwt-client-to-jax-rs-jersey-server/</guid>
<description><![CDATA[Stay tuned …]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Stay tuned … </p>
<p><img style="border-width:0;" border="0" src="http://igorshare.files.wordpress.com/2008/02/image4.png?w=213&#38;h=37&#38;h=37" /></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Building GWT web clients [Part 2.1] &ndash; How to control JSON output format from Jersey?]]></title>
<link>http://igorshare.wordpress.com/2009/05/21/building-gwt-web-clients-part-2-1-how-to-control-json-output-format-from-jersey/</link>
<pubDate>Thu, 21 May 2009 21:31:18 +0000</pubDate>
<dc:creator>igormoochnick</dc:creator>
<guid>http://igorshare.wordpress.com/2009/05/21/building-gwt-web-clients-part-2-1-how-to-control-json-output-format-from-jersey/</guid>
<description><![CDATA[As you know that in XML you can represent the same data in variety of ways by using fields, names, a]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>As you know that in XML you can represent the same data in variety of ways by using fields, names, attributes, etc..</p>
<p>The same is true to JSON. In many cases different serializers produce different JSON representation of the same objects.</p>
<p>JAX-RS (as well as Jersey) provide you control over what and how you want to serialize. This is accomplished via providers.</p>
<p>Here is an example of such provider (Note that the class should be marked with @Provider annotation):</p>
<pre>
<pre class="brush: java;">@Provider
public class JAXBContextResolver implements ContextResolver&lt;JAXBContext&gt; {
    private JAXBContext context;
    private Class&lt;?&gt;[] types = { ListDescription.class }; 

    public JAXBContextResolver() throws Exception {
        JSONConfiguration config = JSONConfiguration.natural().build();
        context = new JSONJAXBContext(config, types);
    } 

    public JAXBContext getContext(Class&lt;?&gt; objectType) {
        for (Class&lt;?&gt; type : types) {
            if (type == objectType) {
                return context;
            }
        }
        return null;
    }
}</pre>
</pre>
<p>Note that by creating an appropriate JSONConfiguration (JSONConfiguration.natural().build()) you, in fact, control the output JSON format. The JSONConfiguration class provide 4 different JSON formatters:</p>
<ol>
<li>natural (Jackson)</li>
<li>mapped</li>
<li>mappedJettison</li>
<li>Badgerfish</li>
</ol>
<p>Here is how the output will vary, depending on the choice of the configuration. Don&#8217;t forget that the class should be annotated with  A simple class (with fields (int)ID and (String)Name) added to an ArrayList and then returned back as a @GET return value:</p>
<pre>
<pre class="brush: java;">@XmlRootElement
public class ListDescription
{
	public int ID;
	public String Name;
}

@GET
@Produces({MediaType.APPLICATION_JSON })
public List&lt;DataListInfo&gt; getAllLists()
{
	List&lt;ListDescription&gt; lists = new ArrayList&lt;ListDescription&gt;();
	ListDescription ls = new ListDescription();
	ls.ID = 1;
	ls.Name = &quot;Test&quot;;
	lists.add(ls);
	return lists;
}</pre>
</pre>
<p>This is what you’ll get from each configuration (respectively):</p>
<p><b><u>mappedJettison:</u></b></p>
<pre>
<pre class="brush: css;">
{&quot;listDescriptions&quot;:{&quot;listDescription&quot;:{&quot;ID&quot;:1,&quot;Name&quot;:&quot;Test&quot;}}}
</pre>
</pre>
<p><b><u>mapped:</u></b></p>
<pre>
<pre class="brush: css;">
{&quot;listDescription&quot;:{&quot;ID&quot;:&quot;1&quot;,&quot;Name&quot;:&quot;Test&quot;}}
</pre>
</pre>
<p><b><u>natural (jackson):</u></b></p>
<pre>
<pre class="brush: css;">
[{&quot;ID&quot;:1,&quot;Name&quot;:&quot;Test&quot;}]
</pre>
</pre>
<p><b><u>Badgerfish:</u></b></p>
<pre>
<pre class="brush: css;">
{&quot;listDescriptions&quot;:{&quot;listDescription&quot;:{&quot;ID&quot;:{&quot;$&quot;:&quot;1&quot;},&quot;Name&quot;:{&quot;$&quot;:&quot;Test&quot;}}}}
</pre>
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Building GWT web clients [Part 2] &ndash; How to expose REST-full JAX-RS service with Jersey on Tomcat server?]]></title>
<link>http://igorshare.wordpress.com/2009/05/20/building-gwt-web-clients-part-2-how-to-expose-rest-full-jax-rs-service-with-jersey-on-tomcat-server/</link>
<pubDate>Wed, 20 May 2009 18:27:41 +0000</pubDate>
<dc:creator>igormoochnick</dc:creator>
<guid>http://igorshare.wordpress.com/2009/05/20/building-gwt-web-clients-part-2-how-to-expose-rest-full-jax-rs-service-with-jersey-on-tomcat-server/</guid>
<description><![CDATA[In the previous article (Part 1) we’ve seen how to create a web-based REST-full client (and an appro]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>In the <a href="http://igorshare.wordpress.com/2009/05/18/building-fat-gwt-web-clients-intro-how-to-create-a-gwt-rpc-client/">previous article (Part 1)</a> we’ve seen how to create a web-based REST-full client (and an appropriate server) by using GWT. GWT is not providing any “standard” REST (if you can use this word in REST context at all) interface, but, merely, exposes the server-side logic via a proprietary GWT RPC interface.</p>
<p>Today, the most common REST standard is the JAX-RS specification. By implementing your code along the JAX-RS guidelines you can be rest assured that you can easily switch one REST-RX library with another.</p>
<p>As of today there are a couple of JAX-RS libraries used by the Java community:</p>
<ol>
<li>Jersey </li>
<li>Restlet </li>
<li>Portlet </li>
<li>etc… </li>
</ol>
<p>On the other hand, being a big fan of Spring, I was hoping that Spring will provide the JAX-RS support in it’s Spring v3 release, but, looking at the M3 drop, I have realized that it’s nowhere near that promise (<a href="http://stackoverflow.com/questions/852969/what-is-the-minimal-configuration-for-rest-fully-annotated-service-built-on-sprin">check my discussion on the StackOverflow</a>).</p>
<p>For this post I’m going to use <a href="https://jersey.dev.java.net/">Jersey JAX-RS</a> implementation. Let’s start with creating </p>
<p> <!--more-->
<p>a Dynamic Web Project in Eclipse. I’m going to use:</p>
<ol>
<li>Apache Tomcat v6.0 </li>
<li>Dynamic Web Module v2.5 </li>
<li>Default Configuration for Apache Tomcat v6.0 </li>
</ol>
<p>To add Jersey (1.1.0-ea) into this mix, add the following JARs (from <a href="https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/jersey-1.1.0-ea/jersey/dependencies.html">this obscure installation instructions</a> page) to your build path:</p>
<ol>
<li>asm-3.1.jar </li>
<li>jsr311-api-1.1.jar </li>
<li>jersey-bundle-1.1.0-ea.jar </li>
<li>jersey-json-1.1.0-ea.jar </li>
<li>jaxb-impl-2.1.10.jar </li>
</ol>
<p>Don’t forget to add these JARs to the “Java EE Module Dependencies” (in the properties of the project) as well.</p>
<p>Let’s define our Web Service. By using the JAX-RS specification it becomes extremely easy:</p>
<pre>
<pre class="brush: java;">@PerRequest
@Path(&quot;/contacts&quot;)
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class ContactManagerService {
    final static List&lt;ContactInfo&gt; contacts = new ArrayList&lt;ContactInfo&gt;();
    static {
        contacts.add(new ContactInfo(&quot;Joe&quot;, &quot;Simth&quot;, &quot;Some Company&quot;));
        contacts.add(new ContactInfo(&quot;Tom&quot;, &quot;Doe&quot;, &quot;Another Company&quot;));
    } 

    @GET
    public ContactList getAllContacts()
    {
        return contacts;
    } 

    @GET
    @Path(&quot;{filter}&quot;)
    public ContactList getFilteredContacts(@PathParam(&quot;filter&quot;) String filter)
    {
        ...

        return ContactList.fromContacts( contacts );
    } 

}</pre>
</pre>
<p>A couple of things to notice here:</p>
<ol>
<li>The “root” path to the ContactManager Web service marked by tompost annotation @Path(&#34;/contacts&#34;), is: /contacts </li>
<li>This class returns<font color="#000000"> data in both application/json and application/xml formats. This is defined by the @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) annotations.</font> </li>
<li>The “default” method for this web service is “getAllContacts”. This is happening because this method has NO @Path annotation. </li>
<li>The “getFilteredContacts” will be called if the Web Services URL will contain a non-empty addition to the root URL, like this: /contact/joe
<ol>
<li>Note that this addition should be URL-encoded </li>
<li>If you’d like to replace it with the query param – replace the annotation with the @QueryParam one. In this case the call will look like /contacts?filter=joe </li>
</ol>
</li>
</ol>
<p>The ContactList, that is returned to the client, should be annotated with @XmlRootElement so Jetty will fire up an appropriate the JAXB provider for the serialization (we’ll talk more about providers later):</p>
<pre>
<pre class="brush: java;">@XmlRootElement
public class ContactList { 

    @XmlElement
    protected java.util.List&lt;ContactInfo&gt; contacts; 

    public ContactList() { ... }

}</pre>
</pre>
<p>As you can guess, there is no magic in the world (I, actually, still hope that there is some <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  so, to make our service visible to the outside world, we need to make sure that Tomcat loads Jersey which, in its order, will load and expose our service according to our annotations. This is done via the additional configuration in the web.config file:</p>
<pre>
<pre class="brush: xml;">&lt;!-- Servlets --&gt;
&lt;servlet&gt;
    &lt;servlet-name&gt;ContactManager Web Services&lt;/servlet-name&gt;
    &lt;servlet-class&gt;com.sun.jersey.spi.container.servlet.ServletContainer&lt;/servlet-class&gt;
    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
    &lt;servlet-name&gt;ContactManager Web Services&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;</pre>
</pre>
<p>After completing all the above you can start Tomcat and use any of the available REST test clients like Fiddler, RESTClient or RESTTest (see <a href="http://stackoverflow.com/questions/165720/how-to-debug-restful-services">discussion on StackOverflow</a>) to see our service in action.</p>
<p>The root URL to the ContactManagerService is <a title="http://localhost:8080/ContactManagerServer/services/contacts" href="http://localhost:8080/ContactManagerServer/services/contacts">http://localhost:8080/ContactManagerServer/services/contacts</a>.</p>
<p>If the request will contain header “Accept: application/json” the result will look like this:</p>
<pre>
<pre class="brush: css;">{&quot;contacts&quot;:[{&quot;FirstName&quot;:&quot;Joe&quot;,&quot;LastName&quot;:&quot;Simth&quot;,&quot;Company&quot;:&quot;Some Company&quot;},
{&quot;FirstName&quot;:&quot;Tom&quot;,&quot;LastName&quot;:&quot;Doe&quot;,&quot;Company&quot;:&quot;Another Company&quot;}]}</pre>
</pre>
<p>On the other hand the header “Accept: application/xml” will produce result like this:</p>
<pre>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
&lt;contactList&gt;
	&lt;contacts&gt;&lt;FirstName&gt;Joe&lt;/FirstName&gt;&lt;LastName&gt;Simth&lt;/LastName&gt;&lt;Company&gt;Some Company&lt;/Company&gt;&lt;/contacts&gt;
	&lt;contacts&gt;&lt;FirstName&gt;Tom&lt;/FirstName&gt;&lt;LastName&gt;Doe&lt;/LastName&gt;&lt;Company&gt;Another Company&lt;/Company&gt;&lt;/contacts&gt;
&lt;/contactList&gt;</pre>
</pre>
<p>Disregard format of the returned content for a moment, we&#8217;re going to talk about serialization in later posts.</p>
<p>More information about the JSON support in Jersey can be found in the <a href="https://jersey.dev.java.net/documentation/1.1.0-ea/user-guide.html#json">Jersey User Guide</a>.</p>
<p><a href="http://cid-49af16156c2594a4.skydrive.live.com/self.aspx/Public/Blog%20Source%20Code/GWT%20fat%20Client/ContactManager%20-%20part2.zip"><img style="border-width:0;" border="0" src="http://igorshare.files.wordpress.com/2008/02/image4.png?w=213&#38;h=37&#38;h=37" /></a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Unit Testing Spring Jersey Integration]]></title>
<link>http://codedependents.com/2009/04/20/unit-testing-spring-jersey-integration/</link>
<pubDate>Mon, 20 Apr 2009 02:34:52 +0000</pubDate>
<dc:creator>Benjamin Darfler</dc:creator>
<guid>http://codedependents.com/2009/04/20/unit-testing-spring-jersey-integration/</guid>
<description><![CDATA[Recently, I&#8217;ve been working on a side project which has given me the opportunity to play with ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Recently, I&#8217;ve been working on a side project which has given me the opportunity to play with an interesting Java technology stack.  After a few weekends of working on the build and moving my way up the stack from database to service layer I was at the point of writing a full integration test.  In the past I&#8217;ve done integration testing with an <a href="http://ibatis.apache.org/">iBatis</a>/<a href="http://www.springsource.org/">Spring</a> stack, which, with the help of <a href="http://www.dbunit.org/">DBUnit</a> is a fairly simple exercise.  However, this project is heavily REST based and the addition of <a href="https://jersey.dev.java.net/">Jersey</a> (JAX-RS) was a serious curveball.</p>
<p>To really test the whole stack an embedded webserver is required.  Looking through the Jersey/Spring unit tests they make use of an exploded WAR using <a href="https://glassfish.dev.java.net/">Glassfish</a>.  Assuming this was the optimal solution I added Glassfish to my ivy.xml config and ran an ivy update.  However, once I realized the overwhelming volume of jars being downloaded I decided it was much too heavy weight of a solution.</p>
<p>My next choice was Jetty.  I have had experience with using Jetty in the past but I quickly ran into issues trying to get it working right with Jersey, Spring, and an exploded WAR configuration.  It was then that I saw the GrizzlyServerFactory referenced in another Jersey unit test.  After some prodding and reading into the source code I ended up with the following:</p>
<pre class="brush: java;">
final URI baseUri = UriBuilder.fromUri( &#34;http://localhost/&#34; ).port( 9998 ).build();
final ServletAdapter adapter = new ServletAdapter();
adapter.addInitParameter( &#34;com.sun.jersey.config.property.packages&#34;, &#60;your-package-name&#62; );
adapter.addContextParameter( &#34;contextConfigLocation&#34;,&#34;classpath:applicationContext.xml&#34; );
adapter.addServletListener( &#34;org.springframework.web.context.ContextLoaderListener&#34; );
adapter.setServletInstance( new SpringServlet() );
adapter.setContextPath( baseUri.getPath() );
SelectorThread threadSelector = GrizzlyServerFactory.create( baseUri, adapter );
</pre>
<p>We start by making a base Uri for localhost at a high numbered port.  Then we build the Grizzly ServletAdaptor.  The first parameter is the package name where your Jersey enabled are located.  The next two lines are taken directly from the web.xml file that is used for the actual WAR.  The first is the config location for the Spring Context and the second is the ContextLoaderListener servlet.  Finally we add the Jersey SpringServlet and the context path.  With these two objects created we can build a SelectorThread and begin using the server using the Jersey Client api that I talked about in <a href="http://blog.bdarfler.com/2009/04/20/rest-calls-and-json-results-in-java/">my previous post</a>.  When you are done, don&#8217;t forget to call stopEndpoint() on the SelectorThread when you are done.</p>
<p><strong>EDIT</strong>:</p>
<p>I&#8217;ve recently come across one additional helpful tip regarding this setup. If you need to get access to your ApplicationContext, for instance to get access to the spring managed DataSource for database testing, there is a simple but non obvious way of doing this. The simple part is using Spring&#8217;s built in utilities for getting the application from a ServletContext.</p>
<pre class="brush: java;">

WebApplicationContextUtils.getWebApplicationContext( adapter.getServletInstance().getServletConfig().getServletContext() );
</pre>
<p>However, when I first tried this I got an unexplained null pointer exception. After a long while trying to google around for the answer I gave up and dug into the source code. Turns out you need to add one important property to the ServletAdaptor for this to all work.</p>
<pre class="brush: java;">

adapter.setProperty( &#34;load-on-startup&#34;, 1 );
</pre>
<p>This will force your adaptor to initialize the servlet immediately and you populate the ServletConfig and ServletContext so you can get the ApplicationContext from them.</p>
<p><iframe src='http://digg.com/api/diggthis.php?u=http%3A%2F%2Fdigg.com%2Fprogramming%2FUnit_Testing_Spring_Jersey_Integration' height='82' width='55' frameborder='0' scrolling='no' style='float: right; margin-left: 10px; margin-bottom: 5px; padding: 4px 0 2px 4px; background: #fff;'></iframe></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Unit Testing Spring Jersey Integration]]></title>
<link>http://bdarfler.wordpress.com/2009/04/20/unit-testing-spring-jersey-integration/</link>
<pubDate>Mon, 20 Apr 2009 02:34:52 +0000</pubDate>
<dc:creator>Benjamin Darfler</dc:creator>
<guid>http://bdarfler.wordpress.com/2009/04/20/unit-testing-spring-jersey-integration/</guid>
<description><![CDATA[Recently, I&#8217;ve been working on a side project which has given me the opportunity to play with ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Recently, I&#8217;ve been working on a side project which has given me the opportunity to play with an interesting Java technology stack.  After a few weekends of working on the build and moving my way up the stack from database to service layer I was at the point of writing a full integration test.  In the past I&#8217;ve done integration testing with an <a href="http://ibatis.apache.org/">iBatis</a>/<a href="http://www.springsource.org/">Spring</a> stack, which, with the help of <a href="http://www.dbunit.org/">DBUnit</a> is a fairly simple exercise.  However, this project is heavily REST based and the addition of <a href="https://jersey.dev.java.net/">Jersey</a> (JAX-RS) was a serious curveball.</p>
<p>To really test the whole stack an embedded webserver is required.  Looking through the Jersey/Spring unit tests they make use of an exploded WAR using <a href="https://glassfish.dev.java.net/">Glassfish</a>.  Assuming this was the optimal solution I added Glassfish to my ivy.xml config and ran an ivy update.  However, once I realized the overwhelming volume of jars being downloaded I decided it was much too heavy weight of a solution.</p>
<p>My next choice was Jetty.  I have had experience with using Jetty in the past but I quickly ran into issues trying to get it working right with Jersey, Spring, and an exploded WAR configuration.  It was then that I saw the GrizzlyServerFactory referenced in another Jersey unit test.  After some prodding and reading into the source code I ended up with the following:</p>
<pre class="brush: java;">
final URI baseUri = UriBuilder.fromUri( &quot;http://localhost/&quot; ).port( 9998 ).build();
final ServletAdapter adapter = new ServletAdapter();
adapter.addInitParameter( &quot;com.sun.jersey.config.property.packages&quot;, &lt;your-package-name&gt; );
adapter.addContextParameter( &quot;contextConfigLocation&quot;,&quot;classpath:applicationContext.xml&quot; );
adapter.addServletListener( &quot;org.springframework.web.context.ContextLoaderListener&quot; );
adapter.setServletInstance( new SpringServlet() );
adapter.setContextPath( baseUri.getPath() );
SelectorThread threadSelector = GrizzlyServerFactory.create( baseUri, adapter );
</pre>
<p>We start by making a base Uri for localhost at a high numbered port.  Then we build the Grizzly ServletAdaptor.  The first parameter is the package name where your Jersey enabled are located.  The next two lines are taken directly from the web.xml file that is used for the actual WAR.  The first is the config location for the Spring Context and the second is the ContextLoaderListener servlet.  Finally we add the Jersey SpringServlet and the context path.  With these two objects created we can build a SelectorThread and begin using the server using the Jersey Client api that I talked about in <a href="http://blog.bdarfler.com/2009/04/20/rest-calls-and-json-results-in-java/">my previous post</a>.  When you are done, don&#8217;t forget to call stopEndpoint() on the SelectorThread when you are done.</p>
<p><iframe src='http://digg.com/api/diggthis.php?u=http%3A%2F%2Fdigg.com%2Fprogramming%2FUnit_Testing_Spring_Jersey_Integration' height='82' width='55' frameborder='0' scrolling='no' style='float: right; margin-left: 10px; margin-bottom: 5px; padding: 4px 0 2px 4px; background: #fff;'></iframe></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[REST calls and JSON results in Java]]></title>
<link>http://bdarfler.wordpress.com/2009/04/20/rest-calls-and-json-results-in-java/</link>
<pubDate>Mon, 20 Apr 2009 02:01:46 +0000</pubDate>
<dc:creator>Benjamin Darfler</dc:creator>
<guid>http://bdarfler.wordpress.com/2009/04/20/rest-calls-and-json-results-in-java/</guid>
<description><![CDATA[I recently had the need interact with Twittervision&#8217;s RESTful api from Java. As usual, I start]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I recently had the need interact with <a href="http://twittervision.com/">Twittervision&#8217;s</a> RESTful api from Java.  As usual, I started googling around for a solution but nothing obviously stood out.  There are a handful of RESTful java frameworks, but these focus on providing a RESTful api and not consuming one.  Finally, after an annoyingly difficult search I found an impressively simple solution based on <a href="https://jersey.dev.java.net/">Jersey</a>.</p>
<p>The point to realize is that Jersey provides both a sever and a client api.  To make use of the client api requires three simple lines:</p>
<pre class="brush: java;">
Client client = Client.create();
WebResource webResource = 
client.resource(&quot;http://twittervision.com/user/current_status/bdarfler.json&quot;);
String response = webResource.get(String.class);
</pre>
<p>The result is a string of JSON, but now, how to parse it.  After searching around I ended up settling on <a href="http://code.google.com/p/json-simple/">json-simple</a>.  A few simple lines of code and we can get the address for any twitter user.</p>
<pre class="brush: java;">
final JSONObject jsonObj = (JSONObject) JSON_PARSER.parse( response );
if ( jsonObj != null &amp;#38;&amp;#38; jsonObj.containsKey( &quot;location&quot; ) )
{
final JSONObject location = (JSONObject) jsonObj.get( &quot;location&quot; );
return location.get( &quot;address&quot; ).toString();
}
</pre>
<p>So, once again, simple stuff but not as obvious as I was hoping it would be.</p>
<p><iframe src='http://digg.com/api/diggthis.php?u=http%3A%2F%2Fdigg.com%2Fprogramming%2FREST_calls_and_JSON_results_in_Java' height='82' width='55' frameborder='0' scrolling='no' style='float: right; margin-left: 10px; margin-bottom: 5px; padding: 4px 0 2px 4px; background: #fff;'></iframe></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[RESTEasy 1.0.2.GA Released]]></title>
<link>http://bill.burkecentral.com/2009/02/13/resteasy-102ga-released/</link>
<pubDate>Fri, 13 Feb 2009 00:59:08 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/02/13/resteasy-102ga-released/</guid>
<description><![CDATA[More bugs found by our users. See our release notes on 1.0.2.GA for more details. Next release will ]]></description>
<content:encoded><![CDATA[More bugs found by our users. See our release notes on 1.0.2.GA for more details. Next release will ]]></content:encoded>
</item>
<item>
<title><![CDATA[RESTEasy 1.0.1.GA released, Minor Bug Fixes]]></title>
<link>http://bill.burkecentral.com/2009/01/30/resteasy-101ga-released-minor-bug-fixes/</link>
<pubDate>Fri, 30 Jan 2009 01:24:56 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/01/30/resteasy-101ga-released-minor-bug-fixes/</guid>
<description><![CDATA[Users found a few minor bugs with 1.0.GA.  See our release notes on 1.0.1.GA for more details.  Unle]]></description>
<content:encoded><![CDATA[Users found a few minor bugs with 1.0.GA.  See our release notes on 1.0.1.GA for more details.  Unle]]></content:encoded>
</item>
<item>
<title><![CDATA[Writing RESTFul Java Book]]></title>
<link>http://bill.burkecentral.com/2009/01/29/writing-restful-java-book/</link>
<pubDate>Thu, 29 Jan 2009 13:37:27 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/01/29/writing-restful-java-book/</guid>
<description><![CDATA[I&#8217;ve contracted with O&#8217;Reilly to write a &#8220;RESTFul Java&#8221; book about REST, Jav]]></description>
<content:encoded><![CDATA[I&#8217;ve contracted with O&#8217;Reilly to write a &#8220;RESTFul Java&#8221; book about REST, Jav]]></content:encoded>
</item>
<item>
<title><![CDATA[Getting started with JBoss RESTEasy 1.0]]></title>
<link>http://indiwiz.wordpress.com/2009/01/26/getting-started-with-jboss-resteasy-10/</link>
<pubDate>Mon, 26 Jan 2009 11:07:43 +0000</pubDate>
<dc:creator>subwiz</dc:creator>
<guid>http://indiwiz.wordpress.com/2009/01/26/getting-started-with-jboss-resteasy-10/</guid>
<description><![CDATA[So ready to jump start into JBoss RESTEasy? Dive! Writing the JAX-RS Class The first step, let us wr]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>So ready to jump start into <a href="http://www.jboss.org/resteasy/">JBoss RESTEasy</a>? Dive!</p>
<h3>Writing the JAX-RS Class</h3>
<p>The first step, let us write a simple echo service using JAX-RS:</p>
<pre class="brush: java;">
package testpackage;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;

@Path(&quot;/echo&quot;)
public class Echo {
    @GET
    @Path(&quot;/{message}&quot;)
    public Response echoService(@PathParam(&quot;message&quot;) String message){
        return Response.status(200).entity(message).build();
    }
}
</pre>
<h3>Adding the JBoss RESTEasy dependency to Maven project</h3>
<p>If you are using Maven to build your projects, add the dependency for RESTEasy:</p>
<pre class="brush: xml;">
&lt;dependency&gt;
    &lt;groupId&gt;org.jboss.resteasy&lt;/groupId&gt;
    &lt;artifactId&gt;resteasy-jaxrs&lt;/artifactId&gt;
    &lt;version&gt;1.0.0.GA&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>Also remember to add the JBoss repository to the <tt>pom.xml</tt> (RESTEasy is not available in Maven public repository):</p>
<pre class="brush: xml;">
&lt;repository&gt;
    &lt;id&gt;jboss&lt;/id&gt;
    &lt;url&gt;http://repository.jboss.com/maven2/&lt;/url&gt;
    &lt;releases&gt;
        &lt;enabled&gt;true&lt;/enabled&gt;
    &lt;/releases&gt;
    &lt;snapshots&gt;
        &lt;enabled&gt;false&lt;/enabled&gt;
    &lt;/snapshots&gt;
&lt;/repository&gt;
</pre>
<h3>Configuring web.xml</h3>
<p>The bare minimum needed to have RESTEasy running is:</p>
<pre class="brush: xml;">
&lt;web-app ...&gt;
    ...
    &lt;listener&gt;
        &lt;listener-class&gt;org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap&lt;/listener-class&gt;
    &lt;/listener&gt;

    &lt;servlet&gt;
        &lt;servlet-name&gt;Resteasy&lt;/servlet-name&gt;
        &lt;servlet-class&gt;org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher&lt;/servlet-class&gt;
    &lt;/servlet&gt;

    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;Resteasy&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
    ...
&lt;/web-app&gt;
</pre>
<p>Above, we have just added the RESTEasy servlet and listener. Now we have to make it load our JAX-RS class. This can be done in two ways. One, just let RESTEasy scan the CLASSPATH to identify and load JAX-RS resources:</p>
<pre class="brush: xml;">
&lt;web-app ...&gt;
    ...
    &lt;context-param&gt;
        &lt;param-name&gt;resteasy.scan&lt;/param-name&gt;
        &lt;param-value&gt;true&lt;/param-value&gt;
    &lt;/context-param&gt;
    ...
&lt;/web-app&gt;
</pre>
<p>The other option is to specify the resources manually (use CSV format):</p>
<pre class="brush: xml;">
&lt;web-app ...&gt;
    ...
    &lt;context-param&gt;
        &lt;param-name&gt;resteasy.resources&lt;/param-name&gt;
        &lt;param-value&gt;testpackage.Echo&lt;/param-value&gt;
    &lt;/context-param&gt;
    ...
&lt;/web-app&gt;
</pre>
<p>After deploying this, you may access your application (if your are using default Tomcat/Jetty installation): <a href="http://localhost:8080/resteasytest/echo/hello,world">http://localhost:8080/resteasytest/echo/hello,world</a> (assumes your application is deployed as <tt>resteasytest.war</tt>)</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[JBoss RESTEasy 1.0 Released]]></title>
<link>http://indiwiz.wordpress.com/2009/01/23/jboss-resteasy-10-released/</link>
<pubDate>Fri, 23 Jan 2009 11:11:07 +0000</pubDate>
<dc:creator>subwiz</dc:creator>
<guid>http://indiwiz.wordpress.com/2009/01/23/jboss-resteasy-10-released/</guid>
<description><![CDATA[I have been awaiting the GA release of RESTEasy for some time! Now we have an alternative to Glasssf]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I have been awaiting the GA release of <a href="http://www.jboss.org/resteasy/">RESTEasy</a> for some time! Now we have an alternative to <a href="https://jersey.dev.java.net/">Glasssfish Jersey</a> <a href="http://jcp.org/en/jsr/detail?id=311">JAX-RS</a> engine.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[RESTEasy 1.0.0.GA Released!]]></title>
<link>http://bill.burkecentral.com/2009/01/20/resteasy-100ga-released/</link>
<pubDate>Tue, 20 Jan 2009 22:38:54 +0000</pubDate>
<dc:creator>billburke</dc:creator>
<guid>http://bill.burkecentral.com/2009/01/20/resteasy-100ga-released/</guid>
<description><![CDATA[See more info on blogs.jboss.com.]]></description>
<content:encoded><![CDATA[See more info on blogs.jboss.com.]]></content:encoded>
</item>

</channel>
</rss>
