3 This licence applies to all files in this repository unless otherwise specifically
4 stated inside of the file.
6 ---------------------------------------------------------------------------
7 Copyright (c) 2016 AT&T Intellectual Property
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:
13 http://www.apache.org/licenses/LICENSE-2.0
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 ---------------------------------------------------------------------------
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;
33 import javax.ws.rs.core.MediaType;
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;
43 public class VotingApp {
45 ArrayList<String> lockNames;
46 MusicConnector musicHandle;
47 private final String version="1.0.0";
49 //UPDATE your onboarding information here
50 String namespace = "votingapp";
51 String userId = "abc123d";
52 String password = "password";
54 public VotingApp(String[] musicIps){
55 lockNames = new ArrayList<String>();
56 musicHandle = new MusicConnector(musicIps);
61 * Adds MUSIC's authentication headers into the webresource
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);
69 if (!userId.equals("")) {
70 builder.header("userId", userId);
72 if (!password.equals("")) {
73 builder.header("password", password);
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);
93 ClientConfig clientConfig = new DefaultClientConfig();
95 clientConfig.getFeatures().put(
96 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
98 Client client = Client.create(clientConfig);
100 WebResource webResource = client
101 .resource(musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName);
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);
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)");
119 Map<String,String> consistencyInfo= new HashMap<String, String>();
120 consistencyInfo.put("type", "eventual");
122 JsonTable jtab = new JsonTable();
123 jtab.setFields(fields);
124 jtab.setConsistencyInfo(consistencyInfo);
126 ClientConfig clientConfig = new DefaultClientConfig();
128 clientConfig.getFeatures().put(
129 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
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
137 ClientResponse response = addMusicHeaders(webResource).accept("application/json")
138 .type("application/json").post(ClientResponse.class, jtab);
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());
145 private void checkMusicVersion(){
146 Client client = Client.create();
147 System.out.println(musicHandle.getMusicNodeURL()+"/version");
150 // System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
151 WebResource webResource = client
152 .resource(musicHandle.getMusicNodeURL()+"/version");
155 ClientResponse response = addMusicHeaders(webResource)
156 .accept(MediaType.APPLICATION_JSON).header("Connection", "close").get(ClientResponse.class);
158 if (response.getStatus() != 200) {
159 throw new RuntimeException("Failed : HTTP error code : "
160 + response.getStatus());
163 String output = response.getEntity(Map.class).toString();
165 System.out.println(output);
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);
174 Map<String,String> consistencyInfo= new HashMap<String, String>();
175 consistencyInfo.put("type", "eventual");
177 JsonInsert jIns = new JsonInsert();
178 jIns.setValues(values);
179 jIns.setConsistencyInfo(consistencyInfo);
180 ClientConfig clientConfig = new DefaultClientConfig();
182 clientConfig.getFeatures().put(
183 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
185 Client client = Client.create(clientConfig);
187 String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows";
188 WebResource webResource = client
191 ClientResponse response = addMusicHeaders(webResource).accept("application/json")
192 .type("application/json").post(ClientResponse.class, jIns);
194 if (response.getStatus() < 200 || response.getStatus() > 299)
195 throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+url+" candidate name:"+ candidateName);
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);
207 ClientResponse response = wb.post(ClientResponse.class);
209 if (response.getStatus() != 200) {
210 throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+msg);
213 Map<String,Object> responseMap = response.getEntity(Map.class);
215 String lockid = ((Map<String,String>) responseMap.get("lock")).get("lock");
216 // System.out.println("Server response .... \n");
217 // System.out.println(output);
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);
228 WebResource.Builder wb = addMusicHeaders(webResource).accept(MediaType.APPLICATION_JSON);
230 ClientResponse response = wb.get(ClientResponse.class);
232 Map<String, Object> responseMap = response.getEntity(Map.class);
234 if (response.getStatus() != 200) {
235 throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+ ":" + responseMap);
238 System.out.println(responseMap);
239 Boolean status = responseMap.get("status").equals("SUCCESS");
240 System.out.println("Server response .... " + status);
244 private void unlock(String lockId){
245 Client client = Client.create();
246 WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/locks/release/"+lockId);
248 ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
251 if (response.getStatus() < 200 || response.getStatus()>299) {
252 throw new RuntimeException("Failed : HTTP error code : "
253 + response.getStatus());
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
261 System.out.println("trying to acquire lock!");
263 String lockName = keyspaceName+".votecount."+candidateName;
264 lockNames.add(lockName);
265 String lockId = createLock(lockName);
266 while(acquireLock(lockId) != true);
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);
273 Map<String,String> consistencyInfo= new HashMap<String, String>();
274 consistencyInfo.put("type", "critical");
275 consistencyInfo.put("lockId", lockId);
277 JsonInsert jIns = new JsonInsert();
278 jIns.setValues(values);
279 jIns.setConsistencyInfo(consistencyInfo);
280 ClientConfig clientConfig = new DefaultClientConfig();
282 clientConfig.getFeatures().put(
283 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
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
291 ClientResponse response = addMusicHeaders(webResource).accept("application/json")
292 .type("application/json").put(ClientResponse.class, jIns);
294 Map<String,String> map = response.getEntity(Map.class);
296 if (response.getStatus() < 200 || response.getStatus() > 299)
297 throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+":"+map);
299 //release lock now that the operation is done
304 private void deleteCandidateEntryEventually(String candidateName){
305 Map<String,String> consistencyInfo= new HashMap<String, String>();
306 consistencyInfo.put("type", "eventual");
308 JsonDelete jDel = new JsonDelete();
309 jDel.setConsistencyInfo(consistencyInfo);
310 ClientConfig clientConfig = new DefaultClientConfig();
312 clientConfig.getFeatures().put(
313 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
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
321 ClientResponse response = addMusicHeaders(webResource).accept("application/json")
322 .type("application/json").delete(ClientResponse.class, jDel);
324 if (response.getStatus() < 200 || response.getStatus() > 299)
325 throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus()+"url:"+url);
329 public Map<String,Object> readVoteCountForCandidate(String candidateName){
330 ClientConfig clientConfig = new DefaultClientConfig();
332 clientConfig.getFeatures().put(
333 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
335 Client client = Client.create(clientConfig);
336 String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows?name="+candidateName;
337 WebResource webResource = client
340 ClientResponse response = addMusicHeaders(webResource).accept("application/json").get(ClientResponse.class);
342 if (response.getStatus() < 200 || response.getStatus() > 299)
343 throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
345 Map<String,Object> output = response.getEntity(Map.class);
349 public Map<String,Object> readAllVotes(){
350 ClientConfig clientConfig = new DefaultClientConfig();
352 clientConfig.getFeatures().put(
353 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
355 Client client = Client.create(clientConfig);
356 String url = musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName+"/tables/votecount/rows";
357 WebResource webResource = client
360 ClientResponse response = addMusicHeaders(webResource).accept("application/json").get(ClientResponse.class);
362 if (response.getStatus() < 200 || response.getStatus() > 299)
363 throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
365 Map<String,Object> output = response.getEntity(Map.class);
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
375 private void dropKeySpace(){
376 Map<String,String> consistencyInfo= new HashMap<String, String>();
377 consistencyInfo.put("type", "eventual");
379 JsonKeySpace jsonKp = new JsonKeySpace();
380 jsonKp.setConsistencyInfo(consistencyInfo);
382 ClientConfig clientConfig = new DefaultClientConfig();
384 clientConfig.getFeatures().put(
385 JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
387 Client client = Client.create(clientConfig);
389 WebResource webResource = client
390 .resource(musicHandle.getMusicNodeURL()+"/keyspaces/"+keyspaceName);
392 ClientResponse response = addMusicHeaders(webResource).type("application/json")
393 .delete(ClientResponse.class, jsonKp);
395 if (response.getStatus() < 200 || response.getStatus() > 299)
396 throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
399 private void deleteLock(String lockName){
400 Client client = Client.create();
401 WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/locks/delete/"+lockName);
403 ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
406 if (response.getStatus() <200 || response.getStatus()>299) {
407 throw new RuntimeException("Failed : HTTP error code : "
408 + response.getStatus());
412 private void resetMusic(){
413 Client client = Client.create();
414 WebResource webResource = client.resource(musicHandle.getMusicNodeURL()+"/reset");
416 ClientResponse response = addMusicHeaders(webResource).delete(ClientResponse.class);
419 if (response.getStatus() != 204) {
420 throw new RuntimeException("Failed : HTTP error code : "
421 + response.getStatus());
425 public void deleteAllLocks(){
426 for (String lockName : lockNames) {
427 deleteLock(lockName);
432 public void bootStrap(){
434 createVotingKeyspace();
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");
443 createEntryForCandidate("Judy");
445 createEntryForCandidate("Flash");
447 createEntryForCandidate("Mickey");
451 public void overAllTests(){
452 //update the count atomically
453 updateVoteCountAtomically("Popeye",5);
455 updateVoteCountAtomically("Judy",7);
457 updateVoteCountAtomically("Mickey",8);
459 updateVoteCountAtomically("Flash",2);
463 System.out.println(readAllVotes());
465 System.out.println(readVoteCountForCandidate("Popeye"));
467 System.out.println(readVoteCountForCandidate("Flash"));
469 deleteCandidateEntryEventually("Mickey");
471 System.out.println(readAllVotes());
478 public void flipTest(){
482 public static String executeBashScript(String pathToScript, String arg1, String arg2){
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) {
496 public static void main(String[] args) {
497 long start = System.currentTimeMillis();
499 if (args.length==0) {
500 args = new String[]{"localhost"};
502 for(int i =0; i < 2;++i){
503 VotingApp vHandle = new VotingApp(args);
504 vHandle.overAllTests();
506 System.out.println("=====================================");
507 System.out.println("Test no."+i+" completed:");
509 long diff = System.currentTimeMillis() - start;
510 System.out.println(diff);