Add voting app example 53/55453/1
authorTschaen, Brendan (bt054f) <bt054f@att.com>
Tue, 26 Jun 2018 20:32:37 +0000 (16:32 -0400)
committerTschaen, Brendan (bt054f) <bt054f@att.com>
Tue, 26 Jun 2018 20:44:59 +0000 (16:44 -0400)
Change-Id: Ife1e6ea10cf74e3495ed72bc14a77179665ca327
Issue-ID: MUSIC-82
Signed-off-by: Tschaen, Brendan (bt054f) <bt054f@att.com>
examples/VotingApp/README.md [new file with mode: 0644]
examples/VotingApp/pom.xml [new file with mode: 0644]
examples/VotingApp/src/main/java/main/JsonDelete.java [new file with mode: 0644]
examples/VotingApp/src/main/java/main/JsonInsert.java [new file with mode: 0644]
examples/VotingApp/src/main/java/main/JsonKeySpace.java [new file with mode: 0644]
examples/VotingApp/src/main/java/main/JsonTable.java [new file with mode: 0644]
examples/VotingApp/src/main/java/main/MusicConnector.java [new file with mode: 0644]
examples/VotingApp/src/main/java/main/Util.java [new file with mode: 0644]
examples/VotingApp/src/main/java/main/VotingApp.java [new file with mode: 0644]

diff --git a/examples/VotingApp/README.md b/examples/VotingApp/README.md
new file mode 100644 (file)
index 0000000..bcd37b9
--- /dev/null
@@ -0,0 +1,31 @@
+
+The voting app for MUSIC  illustrates the features of MUSIC as a
+multi-site state management
+service. It is a program that
+maintains state in MUSIC in the form of a vote-count table that has two columns, the candidateName
+and his voteCount. To the external client that is using the voting app to update votes, the
+votingApp provides a simple function to update the
+votecount of the candidate in an exclusive manner. This is possible because of the locking service
+in MUSIC. Since each candidate is a key in MUSIC, the votingapp simply acquires the geo-distributed
+lock and only then upates the count. This guarantees correctness even when clients access different
+end-points across data centers. Further since state is replicated correctly across data-centers,
+even when one of the data centers fail, functioning can continue simply by using the MUSIC end point
+in the other data center. 
+
+The main function in the VotingApp.java is emulating clients from different data centers by randomly
+chosing MUSIC end points. By updating vote counts
+randomly using different MUSIC end points and still receiving the correct total count when doing a
+read, the main function indicates the multi-site capability of MUSIC. 
+
+
+To run the application, make sure you have onboarded the application using music's admin api.
+A curl call using the default values would be:
+curl -X POST \
+  http://localhost:8080/MUSIC/rest/v2/admin/onboardAppWithMusic \
+  -H 'Content-Type: application/json' \
+  -d '{
+"appname"  : "votingapp",
+"userId"   : "abc123d",
+"password" : "password",
+"isAAF"    : false
+}'
diff --git a/examples/VotingApp/pom.xml b/examples/VotingApp/pom.xml
new file mode 100644 (file)
index 0000000..87cac6c
--- /dev/null
@@ -0,0 +1,92 @@
+<!--
+/*
+ * 
+This licence applies to all files in this repository unless otherwise specifically
+stated inside of the file. 
+
+   Copyright (c) 2016 AT&T Intellectual Property
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+-->
+<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>com.att.reserarch.VoteAppForMUSIC</groupId>
+  <artifactId>VoteAppForMUSIC</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  
+    
+       <repositories>
+               <repository>
+                       <id>maven2-repository.java.net</id>
+                       <name>Java.net Repository for Maven</name>
+                       <url>http://download.java.net/maven/2/</url>
+                       <layout>default</layout>
+               </repository>
+       </repositories>
+
+       <dependencies>
+
+               <dependency>
+                       <groupId>com.sun.jersey</groupId>
+                       <artifactId>jersey-server</artifactId>
+                       <version>1.9</version>
+               </dependency>
+               <dependency>
+    <groupId>com.sun.jersey</groupId>
+    <artifactId>jersey-json</artifactId>
+    <version>1.18.1</version>
+</dependency>
+<dependency>
+   <groupId>com.owlike</groupId>
+   <artifactId>genson</artifactId>
+   <version>0.99</version>
+</dependency>
+               <dependency>
+                       <groupId>com.sun.jersey</groupId>
+                       <artifactId>jersey-client</artifactId>
+                       <version>1.9</version>
+               </dependency>
+
+               <dependency>
+                       <groupId>com.sun.jersey</groupId>
+                       <artifactId>jersey-json</artifactId>
+                       <version>1.9</version>
+               </dependency>
+               
+               <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-bundle</artifactId>
+            <version>1.18</version>
+        </dependency>  
+        
+                       <dependency>
+       <groupId>com.googlecode.json-simple</groupId>
+       <artifactId>json-simple</artifactId>
+       <version>1.1</version>
+  </dependency>
+               <dependency>
+                       <groupId>com.datastax.cassandra</groupId>
+                       <artifactId>cassandra-driver-core</artifactId>
+                       <version>3.0.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.zookeeper</groupId>
+                       <artifactId>zookeeper</artifactId>
+                       <version>3.4.6</version>
+               </dependency>
+        
+       </dependencies>
+  
+</project>
\ No newline at end of file
diff --git a/examples/VotingApp/src/main/java/main/JsonDelete.java b/examples/VotingApp/src/main/java/main/JsonDelete.java
new file mode 100644 (file)
index 0000000..9b75f87
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 
+This licence applies to all files in this repository unless otherwise specifically
+stated inside of the file. 
+
+ ---------------------------------------------------------------------------
+   Copyright (c) 2016 AT&T Intellectual Property
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ ---------------------------------------------------------------------------
+
+ */
+package main;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+public class JsonDelete {
+       
+    private ArrayList<String> columns = null;
+    private Map<String,String> consistencyInfo;
+
+       public Map<String, String> getConsistencyInfo() {
+               return consistencyInfo;
+       }
+
+       public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+               this.consistencyInfo = consistencyInfo;
+       }
+
+    public ArrayList<String> getColumns() {
+               return columns;
+       }
+       public void setColumns(ArrayList<String> columns) {
+               this.columns = columns;
+       }
+       String ttl, timestamp;
+
+       public String getTtl() {
+               return ttl;
+       }
+       public void setTtl(String ttl) {
+               this.ttl = ttl;
+       }
+       public String getTimestamp() {
+               return timestamp;
+       }
+       public void setTimestamp(String timestamp) {
+               this.timestamp = timestamp;
+       }
+}
diff --git a/examples/VotingApp/src/main/java/main/JsonInsert.java b/examples/VotingApp/src/main/java/main/JsonInsert.java
new file mode 100644 (file)
index 0000000..a2099c1
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 
+This licence applies to all files in this repository unless otherwise specifically
+stated inside of the file. 
+
+ ---------------------------------------------------------------------------
+   Copyright (c) 2016 AT&T Intellectual Property
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ ---------------------------------------------------------------------------
+
+ */
+package main;
+
+import java.util.Map;
+
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+public class JsonInsert {
+       
+    private Map<String,Object> values;
+    String ttl, timestamp;
+       private Map<String,Object> row_specification;
+    private Map<String,String> consistencyInfo;
+
+       public Map<String, String> getConsistencyInfo() {
+               return consistencyInfo;
+       }
+
+       public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+               this.consistencyInfo = consistencyInfo;
+       }
+
+       public String getTtl() {
+               return ttl;
+       }
+       public void setTtl(String ttl) {
+               this.ttl = ttl;
+       }
+       public String getTimestamp() {
+               return timestamp;
+       }
+       public void setTimestamp(String timestamp) {
+               this.timestamp = timestamp;
+       }
+       public Map<String, Object> getValues() {
+               return values;
+       }
+       public void setValues(Map<String, Object> values) {
+               this.values = values;
+       }
+    public Map<String, Object> getRow_specification() {
+               return row_specification;
+       }
+       public void setRow_specification(Map<String, Object> row_specification) {
+               this.row_specification = row_specification;
+       }
+}
diff --git a/examples/VotingApp/src/main/java/main/JsonKeySpace.java b/examples/VotingApp/src/main/java/main/JsonKeySpace.java
new file mode 100644 (file)
index 0000000..ff7b6c6
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 
+This licence applies to all files in this repository unless otherwise specifically
+stated inside of the file. 
+
+ ---------------------------------------------------------------------------
+   Copyright (c) 2016 AT&T Intellectual Property
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ ---------------------------------------------------------------------------
+
+ */
+package main;
+
+import java.util.Map;
+
+
+public class JsonKeySpace {
+    private Map<String,Object> replicationInfo;
+       private String durabilityOfWrites;
+    private Map<String,String> consistencyInfo;
+
+       public Map<String, String> getConsistencyInfo() {
+               return consistencyInfo;
+       }
+
+       public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+               this.consistencyInfo = consistencyInfo;
+       }
+
+       public Map<String, Object> getReplicationInfo() {
+               return replicationInfo;
+       }
+       
+       public void setReplicationInfo(Map<String, Object> replicationInfo) {
+               this.replicationInfo = replicationInfo;
+       }
+
+       public String getDurabilityOfWrites() {
+               return durabilityOfWrites;
+       }
+       public void setDurabilityOfWrites(String durabilityOfWrites) {
+               this.durabilityOfWrites = durabilityOfWrites;
+       }
+               
+       
+
+}
diff --git a/examples/VotingApp/src/main/java/main/JsonTable.java b/examples/VotingApp/src/main/java/main/JsonTable.java
new file mode 100644 (file)
index 0000000..66171af
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 
+This licence applies to all files in this repository unless otherwise specifically
+stated inside of the file. 
+
+ ---------------------------------------------------------------------------
+   Copyright (c) 2016 AT&T Intellectual Property
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ ---------------------------------------------------------------------------
+
+ */
+package main;
+import java.util.Map;
+
+public class JsonTable {
+    private Map<String,String> fields;
+       private Map<String, Object> properties; 
+    private Map<String,String> consistencyInfo;
+
+
+       public Map<String, String> getConsistencyInfo() {
+               return consistencyInfo;
+       }
+
+       public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+               this.consistencyInfo = consistencyInfo;
+       }
+
+    public Map<String, Object> getProperties() {
+               return properties;
+       }
+
+       public void setProperties(Map<String, Object> properties) {
+               this.properties = properties;
+       }
+    
+       public Map<String, String> getFields() {
+               return fields;
+       }
+
+       public void setFields(Map<String, String> fields) {
+               this.fields = fields;
+       }
+}
diff --git a/examples/VotingApp/src/main/java/main/MusicConnector.java b/examples/VotingApp/src/main/java/main/MusicConnector.java
new file mode 100644 (file)
index 0000000..d6ed20b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 
+This licence applies to all files in this repository unless otherwise specifically
+stated inside of the file. 
+
+ ---------------------------------------------------------------------------
+   Copyright (c) 2016 AT&T Intellectual Property
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ ---------------------------------------------------------------------------
+
+ */
+package main;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Random;
+
+public class MusicConnector {
+       
+       //change this to point to relevant cluster
+       public String[] musicNodes;
+
+       public MusicConnector(String[] musicNodes){
+               this.musicNodes = musicNodes; 
+       }
+       
+       private String getMusicNodeIp(){
+               Random r = new Random();
+               int index = r.nextInt(musicNodes.length);       
+               return musicNodes[index];
+       }
+       
+       public String getMusicNodeURL(){
+                       String musicurl = "http://"+getMusicNodeIp()+":8080/MUSIC/rest/v2";
+                       return musicurl;
+       }
+       
+       public boolean isHostUp(String serverAddress) { 
+               Boolean isUp = false;
+           try {
+                       InetAddress inet = InetAddress.getByName(serverAddress);
+                       isUp = inet.isReachable(1000);  
+               } catch (UnknownHostException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               } catch (IOException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+           return isUp;
+       }
+       
+       /*      
+       private static String getMusicNodeIp(){
+               
+               //return "54.224.168.13";
+               return bigSiteMusicNode;
+               String serverAddress;
+               serverAddress = agaveMusicNode;
+               while(isHostUp(serverAddress) != true)
+                       serverAddress = toggle(serverAddress);
+               return serverAddress;
+       }*/
+}
diff --git a/examples/VotingApp/src/main/java/main/Util.java b/examples/VotingApp/src/main/java/main/Util.java
new file mode 100644 (file)
index 0000000..aefa9a3
--- /dev/null
@@ -0,0 +1,6 @@
+package main;
+
+public class Util {
+       public static final String version="1.0.0";
+
+}
diff --git a/examples/VotingApp/src/main/java/main/VotingApp.java b/examples/VotingApp/src/main/java/main/VotingApp.java
new file mode 100644 (file)
index 0000000..e58c324
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * 
+This licence applies to all files in this repository unless otherwise specifically
+stated inside of the file. 
+
+ ---------------------------------------------------------------------------
+   Copyright (c) 2016 AT&T Intellectual Property
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ ---------------------------------------------------------------------------
+
+ */
+package main;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.json.JSONConfiguration;
+
+public class VotingApp {
+       String keyspaceName;
+       ArrayList<String> lockNames;
+       MusicConnector musicHandle;
+       private final String version="1.0.0";
+       
+       //UPDATE your onboarding information here
+       String namespace = "votingapp";
+       String userId = "abc123d";
+       String password = "password";
+       
+       public VotingApp(String[] musicIps){
+               lockNames = new ArrayList<String>();    
+               musicHandle = new MusicConnector(musicIps);
+               bootStrap();
+       }
+       
+       /**
+        * Adds MUSIC's authentication headers into the webresource
+        * @param webResource
+        */
+       private Builder addMusicHeaders(WebResource webResource) {
+               Builder builder = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON);
+               if (!namespace.equals("")) {
+                       builder.header("ns", namespace);
+               }
+               if (!userId.equals("")) {
+                       builder.header("userId", userId);
+               }
+               if (!password.equals("")) {
+                       builder.header("password", password);
+               }
+               
+               return builder;
+       }
+       
+       public void createVotingKeyspace(){
+               keyspaceName = "VotingAppForMusic";
+               System.out.println("Voting app version "+ version+" .....");
+               Map<String,Object> replicationInfo = new HashMap<String, Object>();
+               replicationInfo.put("class", "SimpleStrategy");
+               replicationInfo.put("replication_factor", 1);
+               String durabilityOfWrites="false";
+               Map<String,String> consistencyInfo= new HashMap<String, String>();
+               consistencyInfo.put("type", "eventual");
+               JsonKeySpace jsonKp = new JsonKeySpace();
+               jsonKp.setConsistencyInfo(consistencyInfo);
+               jsonKp.setDurabilityOfWrites(durabilityOfWrites);
+               jsonKp.setReplicationInfo(replicationInfo);
+
+               ClientConfig clientConfig = new DefaultClientConfig();
+
+               clientConfig.getFeatures().put(
+                               JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+               Client client = Client.create(clientConfig);
+
+               WebResource webResource = client
+                               .resource(musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName);
+
+               ClientResponse response = addMusicHeaders(webResource).accept("application/json")
+                               .type("application/json").post(ClientResponse.class, jsonKp);
+               if (response.getStatus() < 200 || (response.getStatus() > 299 && response.getStatus()!=400)) { //supress keyspace already exists
+                       Map<String, String> map = response.getEntity(Map.class);
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus() + "- " + map);
+               }
+
+       }
+
+       public void createVotingTable(){
+               Map<String,String> fields = new HashMap<String,String>();
+               fields.put("name", "text");
+               fields.put("count", "varint");
+               fields.put("PRIMARY KEY", "(name)");
+
+
+               Map<String,String> consistencyInfo= new HashMap<String, String>();
+               consistencyInfo.put("type", "eventual");
+
+               JsonTable jtab = new JsonTable();
+               jtab.setFields(fields);
+               jtab.setConsistencyInfo(consistencyInfo);
+
+               ClientConfig clientConfig = new DefaultClientConfig();
+
+               clientConfig.getFeatures().put(
+                               JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+               Client client = Client.create(clientConfig);
+               String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount";
+               System.out.println("create url:"+url);
+               WebResource webResource = client
+                               .resource(url);
+
+               ClientResponse response = addMusicHeaders(webResource).accept("application/json")
+                               .type("application/json").post(ClientResponse.class, jtab);
+
+               System.out.println(response.getEntity(Map.class));
+               if (response.getStatus() < 200 || (response.getStatus() > 299 && response.getStatus()!=400)) 
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
+
+       }
+       private void checkMusicVersion(){
+               Client client = Client.create();
+               System.out.println(musicHandle.getMusicNodeURL()+"/version");
+               
+
+//             System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
+               WebResource webResource = client
+                               .resource(musicHandle.getMusicNodeURL()+"/version");
+               
+
+               ClientResponse response = addMusicHeaders(webResource)
+                               .accept(MediaType.APPLICATION_JSON).header("Connection", "close").get(ClientResponse.class);
+               
+               if (response.getStatus() != 200) {
+                       throw new RuntimeException("Failed : HTTP error code : "
+                                       + response.getStatus());
+               }
+
+               String output = response.getEntity(Map.class).toString();
+
+               System.out.println(output);
+
+       }
+
+       private  void createEntryForCandidate(String candidateName){
+               Map<String,Object> values = new HashMap<String,Object>();
+               values.put("name",candidateName );
+               values.put("count",0);
+
+               Map<String,String> consistencyInfo= new HashMap<String, String>();
+               consistencyInfo.put("type", "eventual");
+
+               JsonInsert jIns = new JsonInsert();
+               jIns.setValues(values);
+               jIns.setConsistencyInfo(consistencyInfo);
+               ClientConfig clientConfig = new DefaultClientConfig();
+
+               clientConfig.getFeatures().put(
+                               JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+               Client client = Client.create(clientConfig);
+
+               String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows";
+               WebResource webResource = client
+                               .resource(url);
+
+               ClientResponse response = addMusicHeaders(webResource).accept("application/json")
+                               .type("application/json").post(ClientResponse.class, jIns);
+
+               if (response.getStatus() < 200 || response.getStatus() > 299) 
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+url+" candidate name:"+ candidateName);
+
+
+       }
+
+       private  String createLock(String lockName){
+               Client client = Client.create();
+               String msg = musicHandle.getMusicNodeURL()+"/locks/create/"+lockName;
+               WebResource webResource = client.resource(msg);
+               System.out.println(msg);
+               WebResource.Builder wb = addMusicHeaders(webResource).accept(MediaType.APPLICATION_JSON);
+
+               ClientResponse response = wb.post(ClientResponse.class);
+
+               if (response.getStatus() != 200) {
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+msg);
+               }
+
+               Map<String,Object> responseMap = response.getEntity(Map.class);
+
+               String lockid = ((Map<String,String>) responseMap.get("lock")).get("lock");
+//             System.out.println("Server response .... \n");
+//             System.out.println(output);
+               return lockid;
+       }
+
+       private  boolean acquireLock(String lockId){
+               Client client = Client.create();
+               String msg = musicHandle.getMusicNodeURL()+"/locks/acquire/"+lockId;
+               System.out.println(msg);
+               WebResource webResource = client.resource(msg);
+
+
+               WebResource.Builder wb = addMusicHeaders(webResource).accept(MediaType.APPLICATION_JSON);
+
+               ClientResponse response = wb.get(ClientResponse.class);
+
+               Map<String, Object> responseMap = response.getEntity(Map.class);
+               
+               if (response.getStatus() != 200) {
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+ ":" + responseMap);
+               }
+
+               System.out.println(responseMap);
+               Boolean status = responseMap.get("status").equals("SUCCESS");
+               System.out.println("Server response .... " + status);
+               return status;
+       }
+
+       private  void unlock(String lockId){
+               Client client = Client.create();
+               WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/locks/release/"+lockId);
+
+               ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
+
+
+               if (response.getStatus() < 200 || response.getStatus()>299) {
+                       throw new RuntimeException("Failed : HTTP error code : "
+                                       + response.getStatus());
+               }
+       }
+
+       private  void updateVoteCountAtomically(String candidateName,int count){
+               /*create lock for the candidate. The music API dictates that
+                * the lock name must be of the form keyspacename.tableName.primaryKeyName
+                * */
+               System.out.println("trying to acquire lock!");
+
+               String lockName = keyspaceName+".votecount."+candidateName;
+               lockNames.add(lockName);
+               String lockId = createLock(lockName);
+               while(acquireLock(lockId) != true);
+               
+               System.out.println("acquired lock!");
+               //update candidate entry if you have the lock
+               Map<String,Object> values = new HashMap<String,Object>();
+               values.put("count",count);
+
+               Map<String,String> consistencyInfo= new HashMap<String, String>();
+               consistencyInfo.put("type", "critical");
+               consistencyInfo.put("lockId", lockId);
+
+               JsonInsert jIns = new JsonInsert();
+               jIns.setValues(values);
+               jIns.setConsistencyInfo(consistencyInfo);
+               ClientConfig clientConfig = new DefaultClientConfig();
+
+               clientConfig.getFeatures().put(
+                               JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+               Client client = Client.create(clientConfig);
+               String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows?name="+candidateName;
+               System.out.println(url);
+               WebResource webResource = client
+                               .resource(url);
+
+               ClientResponse response = addMusicHeaders(webResource).accept("application/json")
+                               .type("application/json").put(ClientResponse.class, jIns);
+
+               Map<String,String> map = response.getEntity(Map.class);
+               
+               if (response.getStatus() < 200 || response.getStatus() > 299) 
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+":"+map);
+
+               //release lock now that the operation is done
+               unlock(lockId);
+
+       }
+
+       private  void deleteCandidateEntryEventually(String candidateName){
+               Map<String,String> consistencyInfo= new HashMap<String, String>();
+               consistencyInfo.put("type", "eventual");
+
+               JsonDelete jDel = new JsonDelete();
+               jDel.setConsistencyInfo(consistencyInfo);
+               ClientConfig clientConfig = new DefaultClientConfig();
+
+               clientConfig.getFeatures().put(
+                               JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+               Client client = Client.create(clientConfig);
+               String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows?name="+candidateName;
+               System.out.println(url);
+               WebResource webResource = client
+                               .resource(url);
+
+               ClientResponse response = addMusicHeaders(webResource).accept("application/json")
+                               .type("application/json").delete(ClientResponse.class, jDel);
+
+               if (response.getStatus() < 200 || response.getStatus() > 299) 
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+url);
+
+       }
+
+       public  Map<String,Object> readVoteCountForCandidate(String candidateName){
+               ClientConfig clientConfig = new DefaultClientConfig();
+
+               clientConfig.getFeatures().put(
+                               JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+               Client client = Client.create(clientConfig);
+               String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows?name="+candidateName;
+               WebResource webResource = client
+                               .resource(url);
+
+               ClientResponse response = addMusicHeaders(webResource).accept("application/json").get(ClientResponse.class);
+
+               if (response.getStatus() < 200 || response.getStatus() > 299) 
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
+               
+               Map<String,Object> output = response.getEntity(Map.class);
+               return output;  
+       }
+
+       public  Map<String,Object> readAllVotes(){
+               ClientConfig clientConfig = new DefaultClientConfig();
+
+               clientConfig.getFeatures().put(
+                               JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+               Client client = Client.create(clientConfig);
+               String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows";
+               WebResource webResource = client
+                               .resource(url);
+
+               ClientResponse response = addMusicHeaders(webResource).accept("application/json").get(ClientResponse.class);
+
+               if (response.getStatus() < 200 || response.getStatus() > 299) 
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
+               
+               Map<String,Object> output = response.getEntity(Map.class);
+               return output;  
+       }
+       
+       
+       /*
+        * Unable to use this because of the error: 
+        * Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: java.net.ProtocolException: 
+        * HTTP method DELETE doesn't support output. Seems to be a error in the rest java combination according to the interwebs
+        */
+       private void dropKeySpace(){
+               Map<String,String> consistencyInfo= new HashMap<String, String>();
+               consistencyInfo.put("type", "eventual");
+
+               JsonKeySpace jsonKp = new JsonKeySpace();
+               jsonKp.setConsistencyInfo(consistencyInfo);
+
+               ClientConfig clientConfig = new DefaultClientConfig();
+
+               clientConfig.getFeatures().put(
+                               JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+               Client client = Client.create(clientConfig);
+
+               WebResource webResource = client
+                               .resource(musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName);
+
+               ClientResponse response = addMusicHeaders(webResource).type("application/json")
+                               .delete(ClientResponse.class, jsonKp);
+
+               if (response.getStatus() < 200 || response.getStatus() > 299) 
+                       throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
+       }
+       
+       private void deleteLock(String lockName){
+               Client client = Client.create();
+               WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/locks/delete/"+lockName);
+
+               ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
+
+
+               if (response.getStatus() <200 || response.getStatus()>299) {
+                       throw new RuntimeException("Failed : HTTP error code : "
+                                       + response.getStatus());
+               }
+       }
+
+       private void resetMusic(){
+               Client client = Client.create();
+               WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/reset");
+
+               ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
+
+
+               if (response.getStatus() != 204) {
+                       throw new RuntimeException("Failed : HTTP error code : "
+                                       + response.getStatus());
+               }
+               
+       }
+       public void deleteAllLocks(){
+               for (String lockName : lockNames) {
+                       deleteLock(lockName);
+               }
+       }
+       
+       
+       public void bootStrap(){
+               checkMusicVersion();
+               createVotingKeyspace();
+
+
+               createVotingTable();
+               
+
+               //the next few lines just create an entry in the voting table for all these candidates with vote count as 0
+               createEntryForCandidate("Popeye");
+
+               createEntryForCandidate("Judy");
+
+               createEntryForCandidate("Flash");
+
+               createEntryForCandidate("Mickey");
+
+       }
+       
+       public void overAllTests(){
+               //update the count atomically
+               updateVoteCountAtomically("Popeye",5);
+
+               updateVoteCountAtomically("Judy",7);
+               
+               updateVoteCountAtomically("Mickey",8);
+
+               updateVoteCountAtomically("Flash",2);
+
+               
+               //read votecount                
+               System.out.println(readAllVotes());
+               
+               System.out.println(readVoteCountForCandidate("Popeye"));
+               
+               System.out.println(readVoteCountForCandidate("Flash"));
+
+               deleteCandidateEntryEventually("Mickey");
+
+               System.out.println(readAllVotes());
+
+//             dropKeySpace();
+
+               deleteAllLocks();
+       }
+       
+       public void flipTest(){
+               checkMusicVersion();
+       }
+       
+       public static String executeBashScript(String pathToScript, String arg1, String arg2){
+               try {
+                       ProcessBuilder pb = new ProcessBuilder(pathToScript,arg1, arg2);
+                       final Process process = pb.start();
+                       InputStream is = process.getInputStream();
+                       InputStreamReader isr = new InputStreamReader(is);
+                       BufferedReader br = new BufferedReader(isr);
+                       return br.readLine();
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+               return null;    
+       }
+       
+       public static void main(String[] args) {        
+               long start = System.currentTimeMillis();
+
+               if (args.length==0) {
+                       args = new String[]{"localhost"};
+               }
+               for(int i =0; i < 2;++i){
+                       VotingApp vHandle = new VotingApp(args);
+                       vHandle.overAllTests();
+
+                       System.out.println("=====================================");
+                       System.out.println("Test no."+i+" completed:");
+               }
+               long diff =     System.currentTimeMillis() - start;
+               System.out.println(diff);
+       }
+                       
+
+}
\ No newline at end of file