8846ba22dee4fd34d7422ffe130e851b758e92ed
[music.git] / examples / VotingApp / src / main / java / main / VotingApp.java
1 /*
2  * 
3 This licence applies to all files in this repository unless otherwise specifically
4 stated inside of the file. 
5
6  ---------------------------------------------------------------------------
7    Copyright (c) 2016 AT&T Intellectual Property
8
9    Licensed under the Apache License, Version 2.0 (the "License");
10    you may not use this file except in compliance with the License.
11    You may obtain a copy of the License at:
12
13        http://www.apache.org/licenses/LICENSE-2.0
14
15    Unless required by applicable law or agreed to in writing, software
16    distributed under the License is distributed on an "AS IS" BASIS,
17    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18    See the License for the specific language governing permissions and
19    limitations under the License.
20  ---------------------------------------------------------------------------
21
22  */
23
24 package main;
25 import java.io.BufferedReader;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.InputStreamReader;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.Map;
32
33 import javax.ws.rs.core.MediaType;
34
35 import com.sun.jersey.api.client.Client;
36 import com.sun.jersey.api.client.ClientResponse;
37 import com.sun.jersey.api.client.WebResource;
38 import com.sun.jersey.api.client.WebResource.Builder;
39 import com.sun.jersey.api.client.config.ClientConfig;
40 import com.sun.jersey.api.client.config.DefaultClientConfig;
41 import com.sun.jersey.api.json.JSONConfiguration;
42
43 public class VotingApp {
44     String keyspaceName;
45     ArrayList<String> lockNames;
46     MusicConnector musicHandle;
47     private final String version="1.0.0";
48     
49     //UPDATE your onboarding information here
50     String namespace = "votingapp";
51     String userId = "abc123d";
52     String password = "password";
53     
54     public VotingApp(String[] musicIps){
55         lockNames = new ArrayList<String>();    
56         musicHandle = new MusicConnector(musicIps);
57         bootStrap();
58     }
59     
60     /**
61      * Adds MUSIC's authentication headers into the webresource
62      * @param webResource
63      */
64     private Builder addMusicHeaders(WebResource webResource) {
65         Builder builder = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON);
66         if (!namespace.equals("")) {
67             builder.header("ns", namespace);
68         }
69         if (!userId.equals("")) {
70             builder.header("userId", userId);
71         }
72         if (!password.equals("")) {
73             builder.header("password", password);
74         }
75         
76         return builder;
77     }
78     
79     public void createVotingKeyspace(){
80         keyspaceName = "VotingAppForMusic";
81         System.out.println("Voting app version "+ version+" .....");
82         Map<String,Object> replicationInfo = new HashMap<String, Object>();
83         replicationInfo.put("class", "SimpleStrategy");
84         replicationInfo.put("replication_factor", 1);
85         String durabilityOfWrites="false";
86         Map<String,String> consistencyInfo= new HashMap<String, String>();
87         consistencyInfo.put("type", "eventual");
88         JsonKeySpace jsonKp = new JsonKeySpace();
89         jsonKp.setConsistencyInfo(consistencyInfo);
90         jsonKp.setDurabilityOfWrites(durabilityOfWrites);
91         jsonKp.setReplicationInfo(replicationInfo);
92
93         ClientConfig clientConfig = new DefaultClientConfig();
94
95         clientConfig.getFeatures().put(
96                 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
97
98         Client client = Client.create(clientConfig);
99
100         WebResource webResource = client
101                 .resource(musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName);
102
103         ClientResponse response = addMusicHeaders(webResource).accept("application/json")
104                 .type("application/json").post(ClientResponse.class, jsonKp);
105         if (response.getStatus() < 200 || (response.getStatus() > 299 && response.getStatus()!=400)) { //supress keyspace already exists
106             Map<String, String> map = response.getEntity(Map.class);
107             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus() + "- " + map);
108         }
109
110     }
111
112     public void createVotingTable(){
113         Map<String,String> fields = new HashMap<String,String>();
114         fields.put("name", "text");
115         fields.put("count", "varint");
116         fields.put("PRIMARY KEY", "(name)");
117
118
119         Map<String,String> consistencyInfo= new HashMap<String, String>();
120         consistencyInfo.put("type", "eventual");
121
122         JsonTable jtab = new JsonTable();
123         jtab.setFields(fields);
124         jtab.setConsistencyInfo(consistencyInfo);
125
126         ClientConfig clientConfig = new DefaultClientConfig();
127
128         clientConfig.getFeatures().put(
129                 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
130
131         Client client = Client.create(clientConfig);
132         String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount";
133         System.out.println("create url:"+url);
134         WebResource webResource = client
135                 .resource(url);
136
137         ClientResponse response = addMusicHeaders(webResource).accept("application/json")
138                 .type("application/json").post(ClientResponse.class, jtab);
139
140         System.out.println(response.getEntity(Map.class));
141         if (response.getStatus() < 200 || (response.getStatus() > 299 && response.getStatus()!=400)) 
142             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
143
144     }
145     private void checkMusicVersion(){
146         Client client = Client.create();
147         System.out.println(musicHandle.getMusicNodeURL()+"/version");
148         
149
150 //        System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
151         WebResource webResource = client
152                 .resource(musicHandle.getMusicNodeURL()+"/version");
153         
154
155         ClientResponse response = addMusicHeaders(webResource)
156                 .accept(MediaType.APPLICATION_JSON).header("Connection", "close").get(ClientResponse.class);
157         
158         if (response.getStatus() != 200) {
159             throw new RuntimeException("Failed : HTTP error code : "
160                     + response.getStatus());
161         }
162
163         String output = response.getEntity(Map.class).toString();
164
165         System.out.println(output);
166
167     }
168
169     private  void createEntryForCandidate(String candidateName){
170         Map<String,Object> values = new HashMap<String,Object>();
171         values.put("name",candidateName );
172         values.put("count",0);
173
174         Map<String,String> consistencyInfo= new HashMap<String, String>();
175         consistencyInfo.put("type", "eventual");
176
177         JsonInsert jIns = new JsonInsert();
178         jIns.setValues(values);
179         jIns.setConsistencyInfo(consistencyInfo);
180         ClientConfig clientConfig = new DefaultClientConfig();
181
182         clientConfig.getFeatures().put(
183                 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
184
185         Client client = Client.create(clientConfig);
186
187         String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows";
188         WebResource webResource = client
189                 .resource(url);
190
191         ClientResponse response = addMusicHeaders(webResource).accept("application/json")
192                 .type("application/json").post(ClientResponse.class, jIns);
193
194         if (response.getStatus() < 200 || response.getStatus() > 299) 
195             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+url+" candidate name:"+ candidateName);
196
197
198     }
199
200     private  String createLock(String lockName){
201         Client client = Client.create();
202         String msg = musicHandle.getMusicNodeURL()+"/locks/create/"+lockName;
203         WebResource webResource = client.resource(msg);
204         System.out.println(msg);
205         WebResource.Builder wb = addMusicHeaders(webResource).accept(MediaType.APPLICATION_JSON);
206
207         ClientResponse response = wb.post(ClientResponse.class);
208
209         if (response.getStatus() != 200) {
210             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+msg);
211         }
212
213         Map<String,Object> responseMap = response.getEntity(Map.class);
214
215         String lockid = ((Map<String,String>) responseMap.get("lock")).get("lock");
216 //        System.out.println("Server response .... \n");
217 //        System.out.println(output);
218         return lockid;
219     }
220
221     private  boolean acquireLock(String lockId){
222         Client client = Client.create();
223         String msg = musicHandle.getMusicNodeURL()+"/locks/acquire/"+lockId;
224         System.out.println(msg);
225         WebResource webResource = client.resource(msg);
226
227
228         WebResource.Builder wb = addMusicHeaders(webResource).accept(MediaType.APPLICATION_JSON);
229
230         ClientResponse response = wb.get(ClientResponse.class);
231
232         Map<String, Object> responseMap = response.getEntity(Map.class);
233         
234         if (response.getStatus() != 200) {
235             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+ ":" + responseMap);
236         }
237
238         System.out.println(responseMap);
239         Boolean status = responseMap.get("status").equals("SUCCESS");
240         System.out.println("Server response .... " + status);
241         return status;
242     }
243
244     private  void unlock(String lockId){
245         Client client = Client.create();
246         WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/locks/release/"+lockId);
247
248         ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
249
250
251         if (response.getStatus() < 200 || response.getStatus()>299) {
252             throw new RuntimeException("Failed : HTTP error code : "
253                     + response.getStatus());
254         }
255     }
256
257     private  void updateVoteCountAtomically(String candidateName,int count){
258         /*create lock for the candidate. The music API dictates that
259          * the lock name must be of the form keyspacename.tableName.primaryKeyName
260          * */
261         System.out.println("trying to acquire lock!");
262
263         String lockName = keyspaceName+".votecount."+candidateName;
264         lockNames.add(lockName);
265         String lockId = createLock(lockName);
266         while(acquireLock(lockId) != true);
267         
268         System.out.println("acquired lock!");
269         //update candidate entry if you have the lock
270         Map<String,Object> values = new HashMap<String,Object>();
271         values.put("count",count);
272
273         Map<String,String> consistencyInfo= new HashMap<String, String>();
274         consistencyInfo.put("type", "critical");
275         consistencyInfo.put("lockId", lockId);
276
277         JsonInsert jIns = new JsonInsert();
278         jIns.setValues(values);
279         jIns.setConsistencyInfo(consistencyInfo);
280         ClientConfig clientConfig = new DefaultClientConfig();
281
282         clientConfig.getFeatures().put(
283                 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
284
285         Client client = Client.create(clientConfig);
286         String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows?name="+candidateName;
287         System.out.println(url);
288         WebResource webResource = client
289                 .resource(url);
290
291         ClientResponse response = addMusicHeaders(webResource).accept("application/json")
292                 .type("application/json").put(ClientResponse.class, jIns);
293
294         Map<String,String> map = response.getEntity(Map.class);
295         
296         if (response.getStatus() < 200 || response.getStatus() > 299) 
297             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+":"+map);
298
299         //release lock now that the operation is done
300         unlock(lockId);
301
302     }
303
304     private  void deleteCandidateEntryEventually(String candidateName){
305         Map<String,String> consistencyInfo= new HashMap<String, String>();
306         consistencyInfo.put("type", "eventual");
307
308         JsonDelete jDel = new JsonDelete();
309         jDel.setConsistencyInfo(consistencyInfo);
310         ClientConfig clientConfig = new DefaultClientConfig();
311
312         clientConfig.getFeatures().put(
313                 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
314
315         Client client = Client.create(clientConfig);
316         String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows?name="+candidateName;
317         System.out.println(url);
318         WebResource webResource = client
319                 .resource(url);
320
321         ClientResponse response = addMusicHeaders(webResource).accept("application/json")
322                 .type("application/json").delete(ClientResponse.class, jDel);
323
324         if (response.getStatus() < 200 || response.getStatus() > 299) 
325             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+url);
326
327     }
328
329     public  Map<String,Object> readVoteCountForCandidate(String candidateName){
330         ClientConfig clientConfig = new DefaultClientConfig();
331
332         clientConfig.getFeatures().put(
333                 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
334
335         Client client = Client.create(clientConfig);
336         String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows?name="+candidateName;
337         WebResource webResource = client
338                 .resource(url);
339
340         ClientResponse response = addMusicHeaders(webResource).accept("application/json").get(ClientResponse.class);
341
342         if (response.getStatus() < 200 || response.getStatus() > 299) 
343             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
344         
345         Map<String,Object> output = response.getEntity(Map.class);
346         return output;    
347     }
348
349     public  Map<String,Object> readAllVotes(){
350         ClientConfig clientConfig = new DefaultClientConfig();
351
352         clientConfig.getFeatures().put(
353                 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
354
355         Client client = Client.create(clientConfig);
356         String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows";
357         WebResource webResource = client
358                 .resource(url);
359
360         ClientResponse response = addMusicHeaders(webResource).accept("application/json").get(ClientResponse.class);
361
362         if (response.getStatus() < 200 || response.getStatus() > 299) 
363             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
364         
365         Map<String,Object> output = response.getEntity(Map.class);
366         return output;    
367     }
368     
369     
370     /*
371      * Unable to use this because of the error: 
372      * Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: java.net.ProtocolException: 
373      * HTTP method DELETE doesn't support output. Seems to be a error in the rest java combination according to the interwebs
374      */
375     private void dropKeySpace(){
376         Map<String,String> consistencyInfo= new HashMap<String, String>();
377         consistencyInfo.put("type", "eventual");
378
379         JsonKeySpace jsonKp = new JsonKeySpace();
380         jsonKp.setConsistencyInfo(consistencyInfo);
381
382         ClientConfig clientConfig = new DefaultClientConfig();
383
384         clientConfig.getFeatures().put(
385                 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
386
387         Client client = Client.create(clientConfig);
388
389         WebResource webResource = client
390                 .resource(musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName);
391
392         ClientResponse response = addMusicHeaders(webResource).type("application/json")
393                 .delete(ClientResponse.class, jsonKp);
394
395         if (response.getStatus() < 200 || response.getStatus() > 299) 
396             throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
397     }
398     
399     private void deleteLock(String lockName){
400         Client client = Client.create();
401         WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/locks/delete/"+lockName);
402
403         ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
404
405
406         if (response.getStatus() <200 || response.getStatus()>299) {
407             throw new RuntimeException("Failed : HTTP error code : "
408                     + response.getStatus());
409         }
410     }
411
412     private void resetMusic(){
413         Client client = Client.create();
414         WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/reset");
415
416         ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
417
418
419         if (response.getStatus() != 204) {
420             throw new RuntimeException("Failed : HTTP error code : "
421                     + response.getStatus());
422         }
423         
424     }
425     public void deleteAllLocks(){
426         for (String lockName : lockNames) {
427             deleteLock(lockName);
428         }
429     }
430     
431     
432     public void bootStrap(){
433         checkMusicVersion();
434         createVotingKeyspace();
435
436
437         createVotingTable();
438         
439
440         //the next few lines just create an entry in the voting table for all these candidates with vote count as 0
441         createEntryForCandidate("Popeye");
442
443         createEntryForCandidate("Judy");
444
445         createEntryForCandidate("Flash");
446
447         createEntryForCandidate("Mickey");
448
449     }
450     
451     public void overAllTests(){
452         //update the count atomically
453         updateVoteCountAtomically("Popeye",5);
454
455         updateVoteCountAtomically("Judy",7);
456         
457         updateVoteCountAtomically("Mickey",8);
458
459         updateVoteCountAtomically("Flash",2);
460
461         
462         //read votecount         
463         System.out.println(readAllVotes());
464         
465         System.out.println(readVoteCountForCandidate("Popeye"));
466         
467         System.out.println(readVoteCountForCandidate("Flash"));
468
469         deleteCandidateEntryEventually("Mickey");
470
471         System.out.println(readAllVotes());
472
473 //        dropKeySpace();
474
475         deleteAllLocks();
476     }
477     
478     public void flipTest(){
479         checkMusicVersion();
480     }
481     
482     public static String executeBashScript(String pathToScript, String arg1, String arg2){
483         try {
484             ProcessBuilder pb = new ProcessBuilder(pathToScript,arg1, arg2);
485             final Process process = pb.start();
486             InputStream is = process.getInputStream();
487             InputStreamReader isr = new InputStreamReader(is);
488             BufferedReader br = new BufferedReader(isr);
489             return br.readLine();
490         } catch (IOException e) {
491             e.printStackTrace();
492         }
493         return null;    
494     }
495     
496     public static void main(String[] args) {    
497         long start = System.currentTimeMillis();
498
499         if (args.length==0) {
500             args = new String[]{"localhost"};
501         }
502         for(int i =0; i < 2;++i){
503             VotingApp vHandle = new VotingApp(args);
504             vHandle.overAllTests();
505
506             System.out.println("=====================================");
507             System.out.println("Test no."+i+" completed:");
508         }
509         long diff =     System.currentTimeMillis() - start;
510         System.out.println(diff);
511     }
512             
513
514 }