Merge branch 'develop'
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..af8bd9e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: java
+jdk:
+  - oraclejdk7
+  - openjdk7
+  - openjdk6
+env:
+  - JAVA_OPTS=-Xmx1024m
+before_script:
+  - ulimit -n 64000
+  - ulimit -u 64000
diff --git a/README.md b/README.md
index a915768..2f9a2c2 100644
--- a/README.md
+++ b/README.md
@@ -1,111 +1,160 @@
 PredictionIO Java SDK
 =====================
 
-Getting Started
----------------
 
-### By Maven
+Getting Started
+===============
+
+
+By Maven
+--------
 
 If you have a Maven project, simply add the dependency to your `pom.xml`.
 
-    <project ...>
-        ...
-        <dependencies>
-            <dependency>
-                <groupId>io.prediction</groupId>
-                <artifactId>client</artifactId>
-                <version>0.6.1</version>
-            </dependency>
-        </dependencies>
-        ...
+```XML
+<project ...>
+    ...
+    <dependencies>
+        <dependency>
+            <groupId>io.prediction</groupId>
+            <artifactId>client</artifactId>
+            <version>0.6.2-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+    ...
+```
 
-### By Ivy
+
+By Ivy
+------
 
 If you use Ivy, simply add the dependency to your `ivy.xml`.
 
-    <ivy-module ...>
+```XML
+<ivy-module ...>
+    ...
+    <dependencies>
+        <dependency org="io.prediction" name="client" rev="0.6.2-SNAPSHOT" />
         ...
-        <dependencies>
-            <dependency org="io.prediction" name="client" rev="0.6.1" />
-            ...
-        </dependencies>
-        ...
+    </dependencies>
+    ...
+```
 
-### sbt
+
+sbt
+---
 
 If you have an sbt project, add the library dependency to your build definition.
 
-    libraryDependencies += "io.prediction" % "client" % "0.6.1"
+```Scala
+libraryDependencies += "io.prediction" % "client" % "0.6.2-SNAPSHOT"
+```
 
-### Building from Source
+
+Building from Source
+--------------------
 
 Assuming you are cloning to your home directory.
 
-    cd ~
-    git clone git://github.com/PredictionIO/PredictionIO-Java-SDK.git
+```sh
+cd ~
+git clone git://github.com/PredictionIO/PredictionIO-Java-SDK.git
+```
 
 To build this SDK you will need Maven 3+. Run the following to publish the module to your local Maven repository.
 
-    cd ~/PredictionIO-Java-SDK
-    mvn clean install
+```sh
+cd ~/PredictionIO-Java-SDK
+mvn clean install
+```
 
 Run the following to generate API documentation.
 
-    cd ~/PredictionIO-Java-SDK
-    mvn clean javadoc:javadoc
+```sh
+cd ~/PredictionIO-Java-SDK
+mvn clean javadoc:javadoc
+```
+
 
 Examples
---------
+========
 
-### Download Source
+
+Download Source
+---------------
 
 If you have not already cloned the repository from the section above, do
 
-    cd ~
-    git clone git://github.com/PredictionIO/PredictionIO-Java-SDK.git
+```sh
+cd ~
+git clone git://github.com/PredictionIO/PredictionIO-Java-SDK.git
+```
 
-### Running the Sample Android Client
 
-Detailed instructions can be found at our [main documentation site](http://docs.prediction.io/current/tutorials/android-client.html).
+Running the Sample Android Client
+---------------------------------
 
-### Running CLI Examples
+Detailed instructions can be found at our
+[main documentation site](http://docs.prediction.io/current/tutorials/android-client.html).
 
-#### Building
+
+Running CLI Examples
+--------------------
+
+
+### Building
 
 If your PredictionIO server is not at localhost, edit the source and replace API URLs with your PredictionIO server host.
 
 To build these examples you will need Maven 3+.
 Run the following in each example's directory, e.g.
 
-    cd ~/PredictionIO-Java-SDK/examples/import
-    mvn clean compile assembly:single
-    cd ~/PredictionIO-Java-SDK/examples/simpletasks1
-    mvn clean compile assembly:single
+```sh
+cd ~/PredictionIO-Java-SDK/examples/import
+mvn clean compile assembly:single
+cd ~/PredictionIO-Java-SDK/examples/simpletasks1
+mvn clean compile assembly:single
+```
 
 These will create JAR files with all dependencies built in.
 
-#### Try It Now
+
+### Try It Now
 
 First, you need to create an Application on PredictionIO and obtain an appkey.
 
 To import the provided small sample data:
 
-    cd ~/PredictionIO-Java-SDK/examples/import
-    java -jar target/sample-import-<latest version>.jar <your appkey here> sampledata/sample1.txt 
+```sh
+cd ~/PredictionIO-Java-SDK/examples/import
+java -jar target/sample-import-<latest version>.jar <your appkey here> sampledata/sample1.txt 
+```
 
 You will then have to create an engine and make sure that it's up and running. It may take an hour for the prediction results to be generated.  
 
 Then, you can run the sample client of various tasks:
 
-    cd ~/PredictionIO-Java-SDK/examples/simpletasks1
-    java -jar target/sample-client-<latest version>-jar-with-dependencies.jar <your appkey here> <your engine name here>
+```sh
+cd ~/PredictionIO-Java-SDK/examples/simpletasks1
+java -jar target/sample-client-<latest version>-jar-with-dependencies.jar <your appkey here> <your engine name here>
+```
 
 Enjoy!
 
+
 Support
 =======
 
+
 Forum
 -----
 
 https://groups.google.com/group/predictionio-user
+
+
+Issue Tracker
+-------------
+
+https://predictionio.atlassian.net
+
+If you are unsure whether a behavior is an issue, bringing it up in the forum is highly encouraged.
diff --git a/client/pom.xml b/client/pom.xml
index 99673ce..94ca0a3 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -1,99 +1,99 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
+  <modelVersion>4.0.0</modelVersion>
 
-    <parent>
-        <groupId>io.prediction</groupId>
-        <artifactId>sdk</artifactId>
-        <relativePath>../pom.xml</relativePath>
-        <version>0.6.1</version>
-    </parent>
+  <parent>
+    <groupId>io.prediction</groupId>
+    <artifactId>sdk</artifactId>
+    <relativePath>../pom.xml</relativePath>
+    <version>0.7.0</version>
+  </parent>
 
-    <artifactId>client</artifactId>
-    <packaging>jar</packaging>
+  <artifactId>client</artifactId>
+  <packaging>jar</packaging>
 
-    <name>PredictionIO Java SDK: Client</name>
+  <name>PredictionIO Java SDK: Client</name>
 
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    </properties>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
 
-    <dependencies>
-        <dependency>
-            <groupId>com.ning</groupId>
-            <artifactId>async-http-client</artifactId>
-            <version>1.7.21</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.code.gson</groupId>
-            <artifactId>gson</artifactId>
-            <version>2.2.4</version>
-        </dependency>
-        <dependency>
-            <groupId>joda-time</groupId>
-            <artifactId>joda-time</artifactId>
-            <version>2.3</version>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.11</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.github.tomakehurst</groupId>
-            <artifactId>wiremock</artifactId>
-            <version>1.33</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-            <version>1.3</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
+  <dependencies>
+    <dependency>
+      <groupId>com.ning</groupId>
+      <artifactId>async-http-client</artifactId>
+      <version>1.7.21</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+      <version>2.2.4</version>
+    </dependency>
+    <dependency>
+      <groupId>joda-time</groupId>
+      <artifactId>joda-time</artifactId>
+      <version>2.3</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.11</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.github.tomakehurst</groupId>
+      <artifactId>wiremock</artifactId>
+      <version>1.33</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-all</artifactId>
+      <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>1.6</source>
-                    <target>1.6</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-source-plugin</artifactId>
-                <version>2.2.1</version>
-                <executions>
-                    <execution>
-                        <id>attach-sources</id>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-javadoc-plugin</artifactId>
-                <version>2.9</version>
-                <executions>
-                    <execution>
-                        <id>attach-javadocs</id>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>emma-maven-plugin</artifactId>
-                <version>1.0-alpha-3</version>
-            </plugin>
-        </plugins>
-    </build>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-source-plugin</artifactId>
+        <version>2.2.1</version>
+        <executions>
+          <execution>
+            <id>attach-sources</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.9</version>
+        <executions>
+          <execution>
+            <id>attach-javadocs</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>emma-maven-plugin</artifactId>
+        <version>1.0-alpha-3</version>
+      </plugin>
+    </plugins>
+  </build>
 </project>
diff --git a/client/src/main/java/io/prediction/Client.java b/client/src/main/java/io/prediction/Client.java
index 52e3d79..6e8c777 100644
--- a/client/src/main/java/io/prediction/Client.java
+++ b/client/src/main/java/io/prediction/Client.java
@@ -3,18 +3,16 @@
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
 import com.google.gson.JsonParser;
 import com.ning.http.client.*;
 import com.ning.http.client.extra.ThrottleRequestFilter;
 import com.ning.http.client.providers.netty.NettyAsyncHttpProvider;
-import org.joda.time.DateTime;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.concurrent.ExecutionException;
 
 /**
@@ -29,7 +27,7 @@
  * @version 0.6.1
  * @since 0.1
  */
-public class Client {
+public class Client implements Closeable {
     // API base URL constant string
     private static final String defaultApiUrl = "http://localhost:8000";
     private static final String apiFormat = "json";
@@ -44,14 +42,12 @@
     private String apiUrl;
     // Appkey
     private String appkey;
-    // Async HTTP client
-    private AsyncHttpClientConfig config;
     private AsyncHttpClient client;
 
     private JsonParser parser = new JsonParser();
 
     // internal field
-    private String uid = "";
+    private String uid = null;
 
     /**
      * Instantiate a PredictionIO RESTful API client using default values for API URL and thread limit.
@@ -91,14 +87,14 @@
         }
         this.setAppkey(appkey);
         // Async HTTP client config
-        this.config = (new AsyncHttpClientConfig.Builder())
-            .setAllowPoolingConnection(true)
-            .setAllowSslConnectionPool(true)
-            .addRequestFilter(new ThrottleRequestFilter(threadLimit))
-            .setMaximumConnectionsPerHost(threadLimit)
-            .setRequestTimeoutInMs(10000)
-            .setIOThreadMultiplier(threadLimit)
-            .build();
+        AsyncHttpClientConfig config = (new AsyncHttpClientConfig.Builder())
+                .setAllowPoolingConnection(true)
+                .setAllowSslConnectionPool(true)
+                .addRequestFilter(new ThrottleRequestFilter(threadLimit))
+                .setMaximumConnectionsPerHost(threadLimit)
+                .setRequestTimeoutInMs(10000)
+                .setIOThreadMultiplier(threadLimit)
+                .build();
         this.client = new AsyncHttpClient(new NettyAsyncHttpProvider(config), config);
     }
 
@@ -106,6 +102,7 @@
      * Close all connections associated with this client.
      * It is a good practice to always close the client after use.
      */
+    @Override
     public void close() {
         this.client.close();
     }
@@ -222,7 +219,7 @@
      * @param uid ID of the User to be created
      */
     public CreateUserRequestBuilder getCreateUserRequestBuilder(String uid) {
-        return new CreateUserRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, uid);
+        return new CreateUserRequestBuilder(this.apiUrl, apiFormat, this.appkey, uid);
     }
 
     /**
@@ -284,7 +281,7 @@
      * @param uid ID of the User to get
      */
     public FutureAPIResponse getUserAsFuture(String uid) throws IOException {
-        Request request = (new RequestBuilder("GET")).setUrl(this.apiUrl + "/users/" + uid + "." + this.apiFormat).addQueryParameter("pio_appkey", this.appkey).build();
+        Request request = (new RequestBuilder("GET")).setUrl(this.apiUrl + "/users/" + uid + "." + apiFormat).addQueryParameter("pio_appkey", this.appkey).build();
         return new FutureAPIResponse(this.client.executeRequest(request, this.getHandler()));
     }
 
@@ -336,7 +333,7 @@
      */
     public FutureAPIResponse deleteUserAsFuture(String uid) throws IOException {
         RequestBuilder builder = new RequestBuilder("DELETE");
-        builder.setUrl(this.apiUrl + "/users/" + uid + "." + this.apiFormat);
+        builder.setUrl(this.apiUrl + "/users/" + uid + "." + apiFormat);
         builder.addQueryParameter("pio_appkey", this.appkey);
         return new FutureAPIResponse(this.client.executeRequest(builder.build(), this.getHandler()));
     }
@@ -379,7 +376,7 @@
      * @param itypes array of types of the Item
      */
     public CreateItemRequestBuilder getCreateItemRequestBuilder(String iid, String[] itypes) {
-        return new CreateItemRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, iid, itypes);
+        return new CreateItemRequestBuilder(this.apiUrl, apiFormat, this.appkey, iid, itypes);
     }
 
     /**
@@ -442,7 +439,7 @@
      * @param iid ID of the Item to get
      */
     public FutureAPIResponse getItemAsFuture(String iid) throws IOException {
-        Request request = (new RequestBuilder("GET")).setUrl(this.apiUrl + "/items/" + iid + "." + this.apiFormat).addQueryParameter("pio_appkey", this.appkey).build();
+        Request request = (new RequestBuilder("GET")).setUrl(this.apiUrl + "/items/" + iid + "." + apiFormat).addQueryParameter("pio_appkey", this.appkey).build();
         return new FutureAPIResponse(this.client.executeRequest(request, this.getHandler()));
     }
 
@@ -501,7 +498,7 @@
      */
     public FutureAPIResponse deleteItemAsFuture(String iid) throws IOException {
         RequestBuilder builder = new RequestBuilder("DELETE");
-        builder.setUrl(this.apiUrl + "/items/" + iid + "." + this.apiFormat);
+        builder.setUrl(this.apiUrl + "/items/" + iid + "." + apiFormat);
         builder.addQueryParameter("pio_appkey", this.appkey);
         return new FutureAPIResponse(this.client.executeRequest(builder.build(), this.getHandler()));
     }
@@ -547,7 +544,7 @@
      * @param n number of top recommendations to get
      */
     public ItemRecGetTopNRequestBuilder getItemRecGetTopNRequestBuilder(String engine, String uid, int n) {
-        return new ItemRecGetTopNRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, engine, uid, n);
+        return new ItemRecGetTopNRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, uid, n);
     }
 
     /**
@@ -560,10 +557,10 @@
      * @throws UnidentifiedUserException indicates an unidentified user ID error
      */
     public ItemRecGetTopNRequestBuilder getItemRecGetTopNRequestBuilder(String engine, int n) throws UnidentifiedUserException {
-        if (this.uid == "") {
+        if (this.uid == null) {
             throw new UnidentifiedUserException("User ID has not been identified. Please call identify(uid) first.");
         }
-        return new ItemRecGetTopNRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, engine, this.uid, n);
+        return new ItemRecGetTopNRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, this.uid, n);
     }
 
     /**
@@ -577,7 +574,7 @@
      * @param attributes array of item attribute names to be returned with the result
      */
     public ItemRecGetTopNRequestBuilder getItemRecGetTopNRequestBuilder(String engine, String uid, int n, String[] attributes) {
-        return (new ItemRecGetTopNRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, engine, uid, n)).attributes(attributes);
+        return (new ItemRecGetTopNRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, uid, n)).attributes(attributes);
     }
 
     /**
@@ -591,10 +588,10 @@
      * @throws UnidentifiedUserException indicates an unidentified user ID error
      */
     public ItemRecGetTopNRequestBuilder getItemRecGetTopNRequestBuilder(String engine, int n, String[] attributes) throws UnidentifiedUserException {
-        if (this.uid == "") {
+        if (this.uid == null) {
             throw new UnidentifiedUserException("User ID has not been identified. Please call identify(uid) first.");
         }
-        return (new ItemRecGetTopNRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, engine, this.uid, n)).attributes(attributes);
+        return (new ItemRecGetTopNRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, this.uid, n)).attributes(attributes);
     }
 
     /**
@@ -738,7 +735,7 @@
         String message = response.get().getMessage();
 
         if (status == Client.HTTP_OK) {
-            HashMap<String, String[]> results = new HashMap();
+            Map<String, String[]> results = new HashMap<String, String[]>();
             JsonObject messageAsJson = (JsonObject) parser.parse(message);
             for (Map.Entry<String, JsonElement> member : messageAsJson.entrySet()) {
                 results.put(member.getKey(), this.jsonArrayAsStringArray(member.getValue().getAsJsonArray()));
@@ -757,7 +754,7 @@
      * @param n number of top similar items to get
      */
     public ItemSimGetTopNRequestBuilder getItemSimGetTopNRequestBuilder(String engine, String iid, int n) {
-        return new ItemSimGetTopNRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, engine, iid, n);
+        return new ItemSimGetTopNRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, iid, n);
     }
 
     /**
@@ -769,7 +766,7 @@
      * @param attributes array of item attribute names to be returned with the result
      */
     public ItemSimGetTopNRequestBuilder getItemSimGetTopNRequestBuilder(String engine, String iid, int n, String[] attributes) {
-        return new ItemSimGetTopNRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, engine, iid, n).attributes(attributes);
+        return new ItemSimGetTopNRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, iid, n).attributes(attributes);
     }
 
     /**
@@ -876,7 +873,219 @@
         String message = response.get().getMessage();
 
         if (status == Client.HTTP_OK) {
-            HashMap<String, String[]> results = new HashMap();
+            Map<String, String[]> results = new HashMap<String, String[]>();
+            JsonObject messageAsJson = (JsonObject) parser.parse(message);
+            for (Map.Entry<String, JsonElement> member : messageAsJson.entrySet()) {
+                results.put(member.getKey(), this.jsonArrayAsStringArray(member.getValue().getAsJsonArray()));
+            }
+            return results;
+        } else {
+            throw new IOException(message);
+        }
+    }
+
+    /**
+     * Get a get item ranking request builder that can be used to add additional request parameters.
+     *
+     * Using this method overrides the user ID set by {@link Client#identify}.
+     *
+     * @param engine engine name
+     * @param uid ID of the User whose recommendations will be gotten
+     * @param iids IDs of Items to be ranked
+     */
+    public ItemRankGetRankedRequestBuilder getItemRankGetRankedRequestBuilder(String engine, String uid, String[] iids) {
+        return new ItemRankGetRankedRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, uid, iids);
+    }
+
+    /**
+     * Get a get item ranking request builder that can be used to add additional request parameters.
+     * Identified user ID will be used. See {@link Client#identify}.
+     *
+     * @param engine engine name
+     * @param iids IDs of Items to be ranked
+     *
+     * @throws UnidentifiedUserException indicates an unidentified user ID error
+     */
+    public ItemRankGetRankedRequestBuilder getItemRankGetRankedRequestBuilder(String engine, String[] iids) throws UnidentifiedUserException {
+        if (this.uid == null) {
+            throw new UnidentifiedUserException("User ID has not been identified. Please call identify(uid) first.");
+        }
+        return new ItemRankGetRankedRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, this.uid, iids);
+    }
+
+    /**
+     * Get a get item ranking request builder that can be used to add additional request parameters.
+     *
+     * Using this method overrides the user ID set by {@link Client#identify}.
+     *
+     * @param engine engine name
+     * @param uid ID of the User whose recommendations will be gotten
+     * @param iids IDs of Items to be ranked
+     * @param attributes array of item attribute names to be returned with the result
+     */
+    public ItemRankGetRankedRequestBuilder getItemRankGetRankedRequestBuilder(String engine, String uid, String[] iids, String[] attributes) {
+        return (new ItemRankGetRankedRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, uid, iids)).attributes(attributes);
+    }
+
+    /**
+     * Get a get item ranking request builder that can be used to add additional request parameters.
+     * Identified user ID will be used. See {@link Client#identify}.
+     *
+     * @param engine engine name
+     * @param iids IDs of Items to be ranked
+     * @param attributes array of item attribute names to be returned with the result
+     *
+     * @throws UnidentifiedUserException indicates an unidentified user ID error
+     */
+    public ItemRankGetRankedRequestBuilder getItemRankGetRankedRequestBuilder(String engine, String[] iids, String[] attributes) throws UnidentifiedUserException {
+        if (this.uid == null) {
+            throw new UnidentifiedUserException("User ID has not been identified. Please call identify(uid) first.");
+        }
+        return (new ItemRankGetRankedRequestBuilder(this.apiUrl, apiFormat, this.appkey, engine, this.uid, iids)).attributes(attributes);
+    }
+
+    /**
+     * Sends an asynchronous get ranking request to the API.
+     *
+     * @param builder an instance of {@link ItemRankGetRankedRequestBuilder} that will be turned into a request
+     */
+    public FutureAPIResponse getItemRankRankedAsFuture(ItemRankGetRankedRequestBuilder builder) throws IOException {
+        return new FutureAPIResponse(this.client.executeRequest(builder.build(), this.getHandler()));
+    }
+
+    /**
+     * Sends a synchronous get ranking request to the API.
+     *
+     * Using this method overrides the user ID set by {@link Client#identify}.
+     *
+     * @param engine engine name
+     * @param uid ID of the User whose recommendations will be gotten
+     * @param iids IDs of Items to be ranked
+     *
+     * @throws ExecutionException indicates an error in the HTTP backend
+     * @throws InterruptedException indicates an interruption during the HTTP operation
+     * @throws IOException indicates an error from the API response
+     */
+    public String[] getItemRankRanked(String engine, String uid, String[] iids) throws ExecutionException, InterruptedException, IOException {
+        return this.getItemRankRanked(this.getItemRankRankedAsFuture(this.getItemRankGetRankedRequestBuilder(engine, uid, iids)));
+    }
+
+    /**
+     * Sends a synchronous get ranking request to the API.
+     * Identified user ID will be used. See {@link Client#identify}.
+     *
+     * @param engine engine name
+     * @param iids IDs of Items to be ranked
+     *
+     * @throws UnidentifiedUserException indicates an unidentified user ID error
+     * @throws ExecutionException indicates an error in the HTTP backend
+     * @throws InterruptedException indicates an interruption during the HTTP operation
+     * @throws IOException indicates an error from the API response
+     */
+    public String[] getItemRankRanked(String engine, String[] iids) throws UnidentifiedUserException, ExecutionException, InterruptedException, IOException {
+        return this.getItemRankRanked(this.getItemRankRankedAsFuture(this.getItemRankGetRankedRequestBuilder(engine, iids)));
+    }
+
+    /**
+     * Sends a synchronous get ranking request to the API.
+     *
+     * @param builder an instance of {@link ItemRankGetRankedRequestBuilder} that will be turned into a request
+     *
+     * @throws ExecutionException indicates an error in the HTTP backend
+     * @throws InterruptedException indicates an interruption during the HTTP operation
+     * @throws IOException indicates an error from the API response
+     */
+    public String[] getItemRankRanked(ItemRankGetRankedRequestBuilder builder) throws ExecutionException, InterruptedException, IOException {
+        return this.getItemRankRanked(this.getItemRankRankedAsFuture(builder));
+    }
+
+    /**
+     * Synchronize a previously sent asynchronous get ranking request.
+     *
+     * @param response an instance of {@link FutureAPIResponse} returned from {@link Client#getItemRankRankedAsFuture}
+     *
+     * @throws ExecutionException indicates an error in the HTTP backend
+     * @throws InterruptedException indicates an interruption during the HTTP operation
+     * @throws IOException indicates an error from the API response
+     */
+    public String[] getItemRankRanked(FutureAPIResponse response) throws ExecutionException, InterruptedException, IOException {
+        // Do not use getStatus/getMessage directly as they do not pass exceptions
+        int status = response.get().getStatus();
+        String message = response.get().getMessage();
+
+        if (status == Client.HTTP_OK) {
+            JsonObject messageAsJson = (JsonObject) parser.parse(message);
+            JsonArray iidsAsJson = messageAsJson.getAsJsonArray("pio_iids");
+            return this.jsonArrayAsStringArray(iidsAsJson);
+        } else {
+            throw new IOException(message);
+        }
+    }
+
+    /**
+     * Sends a synchronous get ranking request to the API.
+     *
+     * Using this method overrides the user ID set by {@link Client#identify}.
+     *
+     * @param engine engine name
+     * @param uid ID of the User whose recommendations will be gotten
+     * @param iids IDs of Items to be ranked
+     * @param attributes array of item attribute names to be returned with the result
+     *
+     * @throws ExecutionException indicates an error in the HTTP backend
+     * @throws InterruptedException indicates an interruption during the HTTP operation
+     * @throws IOException indicates an error from the API response
+     */
+    public Map<String, String[]> getItemRankRankedWithAttributes(String engine, String uid, String[] iids, String[] attributes) throws ExecutionException, InterruptedException, IOException {
+        return this.getItemRankRankedWithAttributes(this.getItemRankRankedAsFuture(this.getItemRankGetRankedRequestBuilder(engine, uid, iids, attributes)));
+    }
+
+    /**
+     * Sends a synchronous get ranking request to the API.
+     * Identified user ID will be used. See {@link Client#identify}.
+     *
+     * @param engine engine name
+     * @param iids IDs of Items to be ranked
+     * @param attributes array of item attribute names to be returned with the result
+     *
+     * @throws UnidentifiedUserException indicates an unidentified user ID error
+     * @throws ExecutionException indicates an error in the HTTP backend
+     * @throws InterruptedException indicates an interruption during the HTTP operation
+     * @throws IOException indicates an error from the API response
+     */
+    public Map<String, String[]> getItemRankRankedWithAttributes(String engine, String[] iids, String[] attributes) throws UnidentifiedUserException, ExecutionException, InterruptedException, IOException {
+        return this.getItemRankRankedWithAttributes(this.getItemRankRankedAsFuture(this.getItemRankGetRankedRequestBuilder(engine, iids, attributes)));
+    }
+
+    /**
+     * Sends a synchronous get ranking request to the API.
+     *
+     * @param builder an instance of {@link ItemRankGetRankedRequestBuilder} that will be turned into a request
+     *
+     * @throws ExecutionException indicates an error in the HTTP backend
+     * @throws InterruptedException indicates an interruption during the HTTP operation
+     * @throws IOException indicates an error from the API response
+     */
+    public Map<String, String[]> getItemRankRankedWithAttributes(ItemRankGetRankedRequestBuilder builder) throws ExecutionException, InterruptedException, IOException {
+        return this.getItemRankRankedWithAttributes(this.getItemRankRankedAsFuture(builder));
+    }
+
+    /**
+     * Synchronize a previously sent asynchronous get ranking request.
+     *
+     * @param response an instance of {@link FutureAPIResponse} returned from {@link Client#getItemRankRankedAsFuture}
+     *
+     * @throws ExecutionException indicates an error in the HTTP backend
+     * @throws InterruptedException indicates an interruption during the HTTP operation
+     * @throws IOException indicates an error from the API response
+     */
+    public Map<String, String[]> getItemRankRankedWithAttributes(FutureAPIResponse response) throws ExecutionException, InterruptedException, IOException {
+        // Do not use getStatus/getMessage directly as they do not pass exceptions
+        int status = response.get().getStatus();
+        String message = response.get().getMessage();
+
+        if (status == Client.HTTP_OK) {
+            Map<String, String[]> results = new HashMap<String, String[]>();
             JsonObject messageAsJson = (JsonObject) parser.parse(message);
             for (Map.Entry<String, JsonElement> member : messageAsJson.entrySet()) {
                 results.put(member.getKey(), this.jsonArrayAsStringArray(member.getValue().getAsJsonArray()));
@@ -897,7 +1106,7 @@
      * @param iid ID of the Item of this action
      */
     public UserActionItemRequestBuilder getUserActionItemRequestBuilder(String uid, String action, String iid) {
-        UserActionItemRequestBuilder builder = new UserActionItemRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, action, uid, iid);
+        UserActionItemRequestBuilder builder = new UserActionItemRequestBuilder(this.apiUrl, apiFormat, this.appkey, action, uid, iid);
         return builder;
     }
 
@@ -911,10 +1120,10 @@
      * @throws UnidentifiedUserException indicates an unidentified user ID error
      */
     public UserActionItemRequestBuilder getUserActionItemRequestBuilder(String action, String iid) throws UnidentifiedUserException {
-        if (this.uid == "") {
+        if (this.uid == null) {
             throw new UnidentifiedUserException("User ID has not been identified. Please call identify(uid) first.");
         }
-        UserActionItemRequestBuilder builder = new UserActionItemRequestBuilder(this.apiUrl, this.apiFormat, this.appkey, action, this.uid, iid);
+        UserActionItemRequestBuilder builder = new UserActionItemRequestBuilder(this.apiUrl, apiFormat, this.appkey, action, this.uid, iid);
         return builder;
     }
 
@@ -1002,7 +1211,7 @@
     /**
      * Synchronize a previously sent asynchronous user-action-on-item request.
      *
-     * @param response an instance of {@link FutureAPIResponse} returned from {@link Client#userRateItemAsFuture}
+     * @param response an instance of {@link FutureAPIResponse} returned from {@link Client#userActionItemAsFuture}
      *
      * @throws ExecutionException indicates an error in the HTTP backend
      * @throws InterruptedException indicates an interruption during the HTTP operation
diff --git a/client/src/main/java/io/prediction/CreateItemRequestBuilder.java b/client/src/main/java/io/prediction/CreateItemRequestBuilder.java
index 3671d92..ef502b6 100644
--- a/client/src/main/java/io/prediction/CreateItemRequestBuilder.java
+++ b/client/src/main/java/io/prediction/CreateItemRequestBuilder.java
@@ -1,16 +1,12 @@
 package io.prediction;
 
 import com.google.gson.JsonObject;
-import org.joda.time.DateTime;
 import com.ning.http.client.Request;
 import com.ning.http.client.RequestBuilder;
+import org.joda.time.DateTime;
 
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
 
 /**
  * Class to build Item requests
diff --git a/client/src/main/java/io/prediction/Item.java b/client/src/main/java/io/prediction/Item.java
index 2aef5e0..7dcd3d3 100644
--- a/client/src/main/java/io/prediction/Item.java
+++ b/client/src/main/java/io/prediction/Item.java
@@ -1,7 +1,5 @@
 package io.prediction;
 
-import org.joda.time.DateTime;
-
 import java.util.Date;
 
 /**
diff --git a/client/src/main/java/io/prediction/ItemRankGetRankedRequestBuilder.java b/client/src/main/java/io/prediction/ItemRankGetRankedRequestBuilder.java
new file mode 100644
index 0000000..a50248c
--- /dev/null
+++ b/client/src/main/java/io/prediction/ItemRankGetRankedRequestBuilder.java
@@ -0,0 +1,75 @@
+package io.prediction;
+
+import com.ning.http.client.Request;
+import com.ning.http.client.RequestBuilder;
+
+/**
+ * Get items' ranking request builder for item ranking engine
+ *
+ * @author The PredictionIO Team (<a href="http://prediction.io">http://prediction.io</a>)
+ * @version 0.7.0
+ * @since 0.7.0
+ */
+
+public class ItemRankGetRankedRequestBuilder {
+    private String apiUrl;
+    private String apiFormat;
+    private String appkey;
+    private String engine;
+    private String uid;
+    private String[] iids;
+    private String[] attributes;
+
+    /**
+     * Instantiate a request builder with mandatory arguments.
+     * <p>
+     * Do not use this directly. Please refer to "See Also".
+     *
+     * @param apiUrl the API URL
+     * @param apiFormat the return format of the API
+     * @param appkey the new app key to be used
+     * @param engine engine name
+     * @param uid UID
+     * @param iids IDs of Items to be ranked
+     *
+     * @see Client#getItemRankGetRankedRequestBuilder
+     */
+    public ItemRankGetRankedRequestBuilder(String apiUrl, String apiFormat, String appkey, String engine, String uid, String[] iids) {
+        this.apiUrl = apiUrl;
+        this.apiFormat = apiFormat;
+        this.appkey = appkey;
+        this.engine = engine;
+        this.uid = uid;
+        this.iids = iids;
+    }
+
+    /**
+     * Add the "attributes" optional argument to the request.
+     *
+     * @param attributes array of item attribute names to be returned with the result
+     */
+    public ItemRankGetRankedRequestBuilder attributes(String[] attributes) {
+        this.attributes = attributes;
+        return this;
+    }
+
+    /**
+     * Build a request.
+     * <p>
+     * Do not use this directly. Please refer to "See Also".
+     *
+     * @see Client#getItemRankRanked(ItemRankGetRankedRequestBuilder)
+     * @see Client#getItemRankRankedAsFuture(ItemRankGetRankedRequestBuilder)
+     */
+    public Request build() {
+        RequestBuilder builder = new RequestBuilder("GET");
+        builder.setUrl(this.apiUrl + "/engines/itemrank/" + this.engine + "/ranked." + this.apiFormat);
+        builder.addQueryParameter("pio_appkey", this.appkey);
+        builder.addQueryParameter("pio_uid", this.uid);
+        builder.addQueryParameter("pio_iids", Utils.arrayToString(this.iids));
+        if (this.attributes != null && this.attributes.length > 0) {
+            builder.addQueryParameter("pio_attributes", Utils.arrayToString(this.attributes));
+        }
+        return builder.build();
+    }
+}
diff --git a/client/src/main/java/io/prediction/UserActionItemRequestBuilder.java b/client/src/main/java/io/prediction/UserActionItemRequestBuilder.java
index 0cddd25..e303042 100644
--- a/client/src/main/java/io/prediction/UserActionItemRequestBuilder.java
+++ b/client/src/main/java/io/prediction/UserActionItemRequestBuilder.java
@@ -65,11 +65,7 @@
      * @param uid the user ID
      * @param iid the item ID
      *
-     * @see Client#getUserRateItemRequestBuilder
-     * @see Client#getUserLikeItemRequestBuilder
-     * @see Client#getUserDislikeItemRequestBuilder
-     * @see Client#getUserViewItemRequestBuilder
-     * @see Client#getUserConversionItemRequestBuilder
+     * @see Client#getUserActionItemRequestBuilder
      */
     public UserActionItemRequestBuilder(String apiUrl, String apiFormat, String appkey, String action, String uid, String iid) {
         this.apiUrl = apiUrl;
@@ -131,11 +127,7 @@
      * <p>
      * Do not use this directly. Please refer to "See Also".
      *
-     * @see Client#userConversionItem(UserActionItemRequestBuilder)
-     * @see Client#userLikeItem(UserActionItemRequestBuilder)
-     * @see Client#userDislikeItem(UserActionItemRequestBuilder)
-     * @see Client#userRateItem(UserActionItemRequestBuilder)
-     * @see Client#userViewItem(UserActionItemRequestBuilder)
+     * @see Client#userActionItem(UserActionItemRequestBuilder)
      */
     public Request build() {
         RequestBuilder builder = new RequestBuilder("POST");
@@ -154,7 +146,7 @@
 
         String actionUrl = "/actions/u2i.";
         requestJson.addProperty("pio_action", this.action);
-        if (this.action == RATE) {
+        if (RATE.equals(this.action)) {
             requestJson.addProperty("pio_rate", Integer.toString(this.rate));
         }
 
diff --git a/client/src/test/java/io/prediction/ClientTest.java b/client/src/test/java/io/prediction/ClientTest.java
index ea2ce6f..bf30505 100644
--- a/client/src/test/java/io/prediction/ClientTest.java
+++ b/client/src/test/java/io/prediction/ClientTest.java
@@ -1,21 +1,23 @@
 package io.prediction;
 
-import java.io.IOException;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.collection.IsArray.array;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
 
 import static com.github.tomakehurst.wiremock.client.WireMock.*;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.collection.IsArray.array;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 /**
  * Tests for {@link Client}.
@@ -28,11 +30,23 @@
     String appkey = "validkey";
     int apiPort = 5784;
     String apiURL = "http://localhost:" + apiPort;
-    Client client = new Client(appkey, apiURL);
+    Client client;
 
     @Rule
     public WireMockRule wireMockRule = new WireMockRule(apiPort);
 
+    @Before
+    public void setUp() {
+        client = new Client(appkey, apiURL);
+    }
+
+    @After
+    public void after() {
+        if (client != null) {
+            client.close();
+        }
+    }
+
     @Test
     public void getStatus() {
         stubFor(get(urlEqualTo("/"))
@@ -174,6 +188,22 @@
     }
 
     @Test
+    public void getItemRecTopNWithoutIdentity() {
+        try {
+            client.getItemRecTopN("greatengine", 5);
+            fail("Should have thrown UnidentifiedUserException");
+        } catch (UnidentifiedUserException e) {
+            // Expected
+        } catch (ExecutionException e) {
+            fail(e.getMessage());
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        } catch (IOException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    @Test
     public void getItemRecTopN() {
         try {
             client.identify("foo");
@@ -288,6 +318,64 @@
     }
 
     @Test
+    public void getItemRankRanked() {
+        String[] iids = {"foo", "bar", "dead", "beef", "baz"};
+        try {
+            client.identify("foo");
+            String[] items = client.getItemRankRanked("ranking", iids);
+            assertThat(items.length, is(5));
+            assertThat(items, is(array(equalTo("baz"), equalTo("bar"), equalTo("foo"), equalTo("beef"), equalTo("dead"))));
+        } catch (UnidentifiedUserException e) {
+            fail(e.getMessage());
+        } catch (ExecutionException e) {
+            fail(e.getMessage());
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        } catch (IOException e) {
+            fail(e.getMessage());
+        }
+
+        try {
+            String[] items = client.getItemRankRanked("ranking", "foo", iids);
+            assertThat(items.length, is(5));
+            assertThat(items, is(array(equalTo("baz"), equalTo("bar"), equalTo("foo"), equalTo("beef"), equalTo("dead"))));
+        } catch (ExecutionException e) {
+            fail(e.getMessage());
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        } catch (IOException e) {
+            fail(e.getMessage());
+        }
+
+        try {
+            client.identify("foo");
+            String[] items = client.getItemRankRanked(client.getItemRankGetRankedRequestBuilder("ranking", iids));
+            assertThat(items.length, is(5));
+            assertThat(items, is(array(equalTo("baz"), equalTo("bar"), equalTo("foo"), equalTo("beef"), equalTo("dead"))));
+        } catch (UnidentifiedUserException e) {
+            fail(e.getMessage());
+        } catch (ExecutionException e) {
+            fail(e.getMessage());
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        } catch (IOException e) {
+            fail(e.getMessage());
+        }
+
+        try {
+            String[] items = client.getItemRankRanked(client.getItemRankGetRankedRequestBuilder("ranking", "foo", iids));
+            assertThat(items.length, is(5));
+            assertThat(items, is(array(equalTo("baz"), equalTo("bar"), equalTo("foo"), equalTo("beef"), equalTo("dead"))));
+        } catch (ExecutionException e) {
+            fail(e.getMessage());
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        } catch (IOException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    @Test
     public void getItemSimTopN() {
         try {
             String[] items = client.getItemSimTopN("anothergreatengine", "foo", 5);
diff --git a/client/src/test/resources/__files/engines/itemrank/ranking/ranked.json b/client/src/test/resources/__files/engines/itemrank/ranking/ranked.json
new file mode 100644
index 0000000..bf74822
--- /dev/null
+++ b/client/src/test/resources/__files/engines/itemrank/ranking/ranked.json
@@ -0,0 +1,9 @@
+{
+    "pio_iids": [
+        "baz",
+        "bar",
+        "foo",
+        "beef",
+        "dead"
+    ]
+}
diff --git a/examples/import/pom.xml b/examples/import/pom.xml
index ea5d18d..d6d13cd 100644
--- a/examples/import/pom.xml
+++ b/examples/import/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>io.prediction.samples</groupId>
     <artifactId>sample-import</artifactId>
-    <version>0.6.1</version>
+    <version>0.6.2-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>PredictionIO Java SDK Examples: Import</name>
 
@@ -11,7 +11,7 @@
         <dependency>
             <groupId>io.prediction</groupId>
             <artifactId>client</artifactId>
-            <version>0.6.1</version>
+            <version>0.6.2-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/examples/import/src/main/java/io/prediction/samples/SampleImport.java b/examples/import/src/main/java/io/prediction/samples/SampleImport.java
index 74475d3..ab71db1 100644
--- a/examples/import/src/main/java/io/prediction/samples/SampleImport.java
+++ b/examples/import/src/main/java/io/prediction/samples/SampleImport.java
@@ -4,14 +4,14 @@
 import io.prediction.FutureAPIResponse;
 
 import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
-import java.util.TreeSet;
 import java.util.StringTokenizer;
+import java.util.TreeSet;
 
 /**
  * Sample data import client using MovieLens data set.
@@ -21,7 +21,7 @@
 public class SampleImport {
     public static void main(String[] args) {
     	/* set appurl to your API server */
-    	String appurl = "http://localhost:8000";
+        String appurl = "http://localhost:8000";
         /* Handle command line arguments */
         String appkey = null;
         String inputFile = null;
@@ -33,27 +33,29 @@
             System.exit(1);
         }
 
-        /* Create a client with an app key */
-        Client client = new Client(appkey);
-
-        /* Data structure */
-        Set uids = new TreeSet<String>();
-        Set iids = new TreeSet<String>();
+        Client client = null;
+        Reader fileReader = null;
 
         /* Read input MovieLens data and send requests to API */
         try {
+            /* Create a client with an app key */
+            client = new Client(appkey, appurl);
+
+            /* Data structure */
+            Set<String> uids = new TreeSet<String>();
+            Set<String> iids = new TreeSet<String>();
+
             /* Get API status */
             System.out.println(client.getStatus());
 
             /* Open data file for reading */
-            FileInputStream fstream = new FileInputStream(inputFile);
-            DataInputStream dstream = new DataInputStream(fstream);
-            BufferedReader reader = new BufferedReader(new InputStreamReader(dstream));
+            fileReader = new FileReader(inputFile);
+            BufferedReader reader = new BufferedReader(fileReader);
 
             /* Some local variables */
             String line;
             int i = 0;
-            ArrayList<FutureAPIResponse> rs = new ArrayList<FutureAPIResponse>();
+            List<FutureAPIResponse> rs = new ArrayList<FutureAPIResponse>();
 
             while ((line = reader.readLine()) != null) {
                 /* Break the line up */
@@ -74,19 +76,19 @@
                 int j;
                 for (j=0; j<5; j++) {
                     FutureAPIResponse r;
- 
+
                     // create all types of actions for testing purpose
                     switch (j) {
-                        case 0: 
+                        case 0:
                             r = client.userActionItemAsFuture(client.getUserActionItemRequestBuilder("view", iid));
                             break;
-                        case 1: 
+                        case 1:
                             r = client.userActionItemAsFuture(client.getUserActionItemRequestBuilder("like", iid));
                             break;
-                        case 2: 
+                        case 2:
                             r = client.userActionItemAsFuture(client.getUserActionItemRequestBuilder("dislike", iid));
                             break;
-                        case 3: 
+                        case 3:
                             r = client.userActionItemAsFuture(client.getUserActionItemRequestBuilder("conversion", iid));
                             break;
                         default:
@@ -107,20 +109,16 @@
 
             }
 
-            dstream.close();
-
             /* Add User and Item IDs asynchronously */
             System.out.println("Sending "+uids.size()+" create User ID requests");
-            for (Iterator uidIter = uids.iterator(); uidIter.hasNext();) {
-                String uid = (String)uidIter.next();
+            for (String uid : uids) {
                 rs.add(client.createUserAsFuture(client.getCreateUserRequestBuilder(uid)));
             }
 
             System.out.println("Sending "+iids.size()+" create Item ID requests");
             String[] itypes = {"movies"};
-            for (Iterator iidIter = iids.iterator(); iidIter.hasNext();) {
-                String iid = (String)iidIter.next();
-                rs.add(client.createItemAsFuture(client.getCreateItemRequestBuilder(iid, itypes).attribute("url", "http://localhost/"+iid+".html").attribute("startT", "ignored")));
+            for (String iid : iids) {
+                rs.add(client.createItemAsFuture(client.getCreateItemRequestBuilder(iid, itypes).attribute("url", "http://localhost/" + iid + ".html").attribute("startT", "ignored")));
             }
 
             /* Synchronize all requests before the program exits */
@@ -131,7 +129,18 @@
             }
         } catch (Exception e) {
             System.err.println("Error: " + e.getMessage());
+            e.printStackTrace();
+        } finally {
+            if (fileReader != null) {
+                try {
+                    fileReader.close();
+                } catch (IOException e) {
+                    System.err.println("Error: " + e.getMessage());
+                }
+            }
+            if (client != null) {
+                client.close();
+            }
         }
-        client.close();
     }
 }
diff --git a/examples/import_deprecated/pom.xml b/examples/import_deprecated/pom.xml
index ea5d18d..d6d13cd 100644
--- a/examples/import_deprecated/pom.xml
+++ b/examples/import_deprecated/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>io.prediction.samples</groupId>
     <artifactId>sample-import</artifactId>
-    <version>0.6.1</version>
+    <version>0.6.2-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>PredictionIO Java SDK Examples: Import</name>
 
@@ -11,7 +11,7 @@
         <dependency>
             <groupId>io.prediction</groupId>
             <artifactId>client</artifactId>
-            <version>0.6.1</version>
+            <version>0.6.2-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/examples/simpletasks1/pom.xml b/examples/simpletasks1/pom.xml
index 1fd1bc9..87719ea 100644
--- a/examples/simpletasks1/pom.xml
+++ b/examples/simpletasks1/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>io.prediction.samples</groupId>
     <artifactId>sample-client</artifactId>
-    <version>0.6.1</version>
+    <version>0.6.2-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>PredictionIO Java SDK Examples: Client</name>
 
@@ -11,7 +11,7 @@
         <dependency>
             <groupId>io.prediction</groupId>
             <artifactId>client</artifactId>
-            <version>0.6.1</version>
+            <version>0.6.2-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/examples/simpletasks1_deprecated/pom.xml b/examples/simpletasks1_deprecated/pom.xml
index 1fd1bc9..87719ea 100644
--- a/examples/simpletasks1_deprecated/pom.xml
+++ b/examples/simpletasks1_deprecated/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>io.prediction.samples</groupId>
     <artifactId>sample-client</artifactId>
-    <version>0.6.1</version>
+    <version>0.6.2-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>PredictionIO Java SDK Examples: Client</name>
 
@@ -11,7 +11,7 @@
         <dependency>
             <groupId>io.prediction</groupId>
             <artifactId>client</artifactId>
-            <version>0.6.1</version>
+            <version>0.6.2-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/examples/simpletasks2/pom.xml b/examples/simpletasks2/pom.xml
index 1fd1bc9..87719ea 100644
--- a/examples/simpletasks2/pom.xml
+++ b/examples/simpletasks2/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>io.prediction.samples</groupId>
     <artifactId>sample-client</artifactId>
-    <version>0.6.1</version>
+    <version>0.6.2-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>PredictionIO Java SDK Examples: Client</name>
 
@@ -11,7 +11,7 @@
         <dependency>
             <groupId>io.prediction</groupId>
             <artifactId>client</artifactId>
-            <version>0.6.1</version>
+            <version>0.6.2-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
diff --git a/pom.xml b/pom.xml
index 5cf8636..ebaece9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,87 +1,106 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>io.prediction</groupId>
-    <artifactId>sdk</artifactId>
-    <version>0.6.1</version>
-    <url>http://prediction.io</url>
-    <packaging>pom</packaging>
-    <name>PredictionIO Java SDK</name>
-    <description>The PredictionIO Java SDK includes an API client and sample code.</description>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>io.prediction</groupId>
+  <artifactId>sdk</artifactId>
+  <version>0.7.0</version>
+  <url>http://prediction.io</url>
+  <packaging>pom</packaging>
+  <name>PredictionIO Java SDK</name>
+  <description>The PredictionIO Java SDK includes an API client and sample code.</description>
 
-    <parent>
-        <groupId>org.sonatype.oss</groupId>
-        <artifactId>oss-parent</artifactId>
-        <version>7</version>
-    </parent>
+  <parent>
+    <groupId>org.sonatype.oss</groupId>
+    <artifactId>oss-parent</artifactId>
+    <version>7</version>
+  </parent>
 
-    <licenses>
-        <license>
-            <name>The Apache Software License, Version 2.0</name>
-            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-            <distribution>repo</distribution>
-        </license>
-    </licenses>
+  <licenses>
+    <license>
+      <name>The Apache Software License, Version 2.0</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
 
-    <developers>
-        <developer>
-            <id>predictionio</id>
-            <name>The PredictionIO Team</name>
-            <email>support@prediction.io</email>
-        </developer>
-    </developers>
+  <developers>
+    <developer>
+      <id>predictionio</id>
+      <name>The PredictionIO Team</name>
+      <email>support@prediction.io</email>
+    </developer>
+  </developers>
 
-    <contributors>
-        <contributor>
-            <name>Cong Qin</name>
-            <email>Cong.Charlie.Qin@gmail.com</email>
-        </contributor>
-    </contributors>
+  <contributors>
+    <contributor>
+      <name>Cong Qin</name>
+      <email>Cong.Charlie.Qin@gmail.com</email>
+    </contributor>
+  </contributors>
 
-    <scm>
-        <connection>scm:git:git@github.com:PredictionIO/PredictionIO-Java-SDK.git</connection>
-        <developerConnection>scm:git:git@github.com:PredictionIO/PredictionIO-Java-SDK.git</developerConnection>
-        <url>git@github.com:PredictionIO/PredictionIO-Java-SDK.git</url>
-    </scm>
+  <scm>
+    <connection>scm:git:git@github.com:PredictionIO/PredictionIO-Java-SDK.git</connection>
+    <developerConnection>scm:git:git@github.com:PredictionIO/PredictionIO-Java-SDK.git</developerConnection>
+    <url>git@github.com:PredictionIO/PredictionIO-Java-SDK.git</url>
+  </scm>
 
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <outputDirectory>${project.build.directory}</outputDirectory>
-    </properties>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    <outputDirectory>${project.build.directory}</outputDirectory>
+  </properties>
 
-    <modules>
-        <module>client</module>
-    </modules>
+  <modules>
+    <module>client</module>
+  </modules>
 
-    <build>
-        <pluginManagement>
-            <plugins>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-compiler-plugin</artifactId>
-                    <version>2.5.1</version>
-                    <configuration>
-                        <encoding>UTF-8</encoding>
-                        <source>1.6</source>
-                        <target>1.6</target>
-                    </configuration>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-gpg-plugin</artifactId>
-                    <executions>
-                        <execution>
-                            <id>sign-artifacts</id>
-                            <phase>verify</phase>
-                            <goals>
-                                <goal>sign</goal>
-                            </goals>
-                        </execution>
-                    </executions>
-                </plugin>
-            </plugins>
-        </pluginManagement>
-    </build>
+  <distributionManagement>
+    <snapshotRepository>
+      <id>ossrh</id>
+      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+    </snapshotRepository>
+    <repository>
+      <id>ossrh</id>
+      <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+    </repository>
+  </distributionManagement>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.5.1</version>
+        <configuration>
+          <encoding>UTF-8</encoding>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-gpg-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>sign-artifacts</id>
+            <phase>verify</phase>
+            <goals>
+              <goal>sign</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.sonatype.plugins</groupId>
+        <artifactId>nexus-staging-maven-plugin</artifactId>
+        <version>1.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <serverId>ossrh</serverId>
+          <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
 
 </project>