2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Modifications Copyright (c) 2019 Samsung
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
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.
21 * ============LICENSE_END=============================================
22 * ====================================================================
25 package org.onap.music.rest;
27 import java.nio.ByteBuffer;
28 import java.util.List;
30 import java.util.UUID;
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.GET;
35 import javax.ws.rs.HeaderParam;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.PUT;
38 import javax.ws.rs.Path;
39 import javax.ws.rs.PathParam;
40 import javax.ws.rs.Produces;
41 import javax.ws.rs.core.Context;
42 import javax.ws.rs.core.MediaType;
43 import javax.ws.rs.core.MultivaluedMap;
44 import javax.ws.rs.core.Response;
45 import javax.ws.rs.core.Response.ResponseBuilder;
46 import javax.ws.rs.core.Response.Status;
47 import javax.ws.rs.core.UriInfo;
49 import org.apache.commons.lang3.StringUtils;
50 import org.onap.music.datastore.PreparedQueryObject;
51 import org.onap.music.datastore.jsonobjects.JsonDelete;
52 import org.onap.music.datastore.jsonobjects.JsonInsert;
53 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
54 import org.onap.music.datastore.jsonobjects.JsonTable;
55 import org.onap.music.datastore.jsonobjects.JsonUpdate;
56 import org.onap.music.eelf.logging.EELFLoggerDelegate;
57 import org.onap.music.exceptions.MusicLockingException;
58 import org.onap.music.exceptions.MusicQueryException;
59 import org.onap.music.eelf.logging.format.AppMessages;
60 import org.onap.music.eelf.logging.format.ErrorSeverity;
61 import org.onap.music.eelf.logging.format.ErrorTypes;
62 import org.onap.music.exceptions.MusicServiceException;
63 import org.onap.music.main.MusicCore;
64 import org.onap.music.datastore.Condition;
65 import org.onap.music.datastore.MusicDataStoreHandle;
66 import org.onap.music.main.MusicUtil;
67 import org.onap.music.main.ResultType;
68 import org.onap.music.main.ReturnType;
69 import org.onap.music.response.jsonobjects.JsonResponse;
71 import com.datastax.driver.core.DataType;
72 import com.datastax.driver.core.ResultSet;
73 import com.datastax.driver.core.TableMetadata;
75 import io.swagger.annotations.Api;
76 import io.swagger.annotations.ApiImplicitParam;
77 import io.swagger.annotations.ApiImplicitParams;
78 import io.swagger.annotations.ApiOperation;
79 import io.swagger.annotations.ApiParam;
80 import io.swagger.annotations.ApiResponses;
81 import io.swagger.annotations.ApiResponse;
82 import io.swagger.annotations.Example;
83 import io.swagger.annotations.ExampleProperty;
86 //@Path("/v{version: [0-9]+}/keyspaces")
87 @Path("/v2/keyspaces")
88 @Api(value = "Data Api")
89 public class RestMusicDataAPI {
91 * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
92 * version back from the client to the server, and from the server back to the client - This
93 * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
94 * version (if not specified by the client on the request) - Contains a single position value
95 * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
96 * request; however, this header should be provided if the client needs to take advantage of
97 * MINOR incremented version functionality - Is mandatory for the server on response
99 *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
100 * troubleshooting purposes only, and will not be provided by the client on request - This will
101 * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
102 * of the MAJOR (if not specified by the client on the request) - Contains a single position
103 * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
104 * server on response (CURRENTLY NOT USED)
106 *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
107 * server on response, and shall include the entire version of the API (e.g. if the full version
108 * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
109 * not using the latest version of the API (CURRENTLY NOT USED)
113 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
114 private static final String XMINORVERSION = "X-minorVersion";
115 private static final String XPATCHVERSION = "X-patchVersion";
116 private static final String NS = "ns";
117 private static final String VERSION = "v2";
118 private static final String PARAMETER_ERROR = "Missing Row Identifier. Please provide the parameter of key=value for the row being selected.";
121 private class RowIdentifier {
122 public String primarKeyValue;
123 public StringBuilder rowIdString;
124 @SuppressWarnings("unused")
125 public PreparedQueryObject queryObject; // the string with all the row
126 // identifiers separated by AND
128 public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
129 PreparedQueryObject queryObject) {
130 this.primarKeyValue = primaryKeyValue;
131 this.rowIdString = rowIdString;
132 this.queryObject = queryObject;
138 * Create Keyspace REST
141 * @param keyspaceName
147 @ApiOperation(value = "Create Keyspace", response = String.class,
148 notes = "This API will not work if MUSIC properties has keyspace.active=false ")
149 @Consumes(MediaType.APPLICATION_JSON)
150 @Produces(MediaType.APPLICATION_JSON)
151 @ApiResponses(value={
152 @ApiResponse(code=200, message = "Success",examples = @Example( value = {
153 @ExampleProperty(mediaType="application/json",value =
154 "{\"message\" : \"Keysapce <keyspace> Created\","
155 + "\"status\" : \"SUCCESS\"}")
157 @ApiResponse(code=400, message = "Failure",examples = @Example( value = {
158 @ExampleProperty(mediaType="application/json",value =
159 "{\"error\" : \"<errorMessage>\","
160 + "\"status\" : \"FAILURE\"}")
163 public Response createKeySpace(
164 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
165 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
166 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
167 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
168 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
169 @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
170 JsonKeySpace kspObject,
171 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) {
173 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
174 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
175 logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName);
176 if (MusicUtil.isKeyspaceActive() ) {
177 logger.info(EELFLoggerDelegate.applicationLogger,"Creating Keyspace " + keyspaceName);
179 if(kspObject == null || kspObject.getReplicationInfo() == null) {
180 response.status(Status.BAD_REQUEST);
181 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
184 String consistency = MusicUtil.EVENTUAL;// for now this needs only eventual consistency
186 PreparedQueryObject queryObject = new PreparedQueryObject();
187 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) {
188 if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency")))
189 queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency"));
191 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
193 long start = System.currentTimeMillis();
194 Map<String, Object> replicationInfo = kspObject.getReplicationInfo();
195 String repString = null;
197 repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
198 } catch (Exception e) {
199 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity
200 .CRITICAL, ErrorTypes.DATAERROR, e);
203 queryObject.appendQueryString(
204 "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
205 if (kspObject.getDurabilityOfWrites() != null) {
206 queryObject.appendQueryString(
207 " AND durable_writes = " + kspObject.getDurabilityOfWrites());
210 queryObject.appendQueryString(";");
211 long end = System.currentTimeMillis();
212 logger.info(EELFLoggerDelegate.applicationLogger,
213 "Time taken for setting up query in create keyspace:" + (end - start));
215 ResultType result = ResultType.FAILURE;
217 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
218 } catch ( MusicQueryException ex) {
219 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.QUERYERROR
220 ,ErrorSeverity.WARN, ErrorTypes.QUERYERROR);
221 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
222 } catch ( MusicServiceException ex) {
223 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity
224 .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
225 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
228 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build();
230 String vError = "Keyspace Creation has been turned off. Contact DBA to create the keyspace or set keyspace.active to true.";
231 logger.info(EELFLoggerDelegate.applicationLogger,vError);
232 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
233 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
236 EELFLoggerDelegate.mdcRemove("keyspace");
244 * @param keyspaceName
250 @ApiOperation(value = "Delete Keyspace", response = String.class,
251 notes = "This API will not work if MUSIC properties has keyspace.active=false ")
252 @Produces(MediaType.APPLICATION_JSON)
253 @ApiResponses(value={
254 @ApiResponse(code=200, message = "Success",examples = @Example( value = {
255 @ExampleProperty(mediaType="application/json",value =
256 "{\"message\" : \"Keysapce <keyspace> Deleted\","
257 + "\"status\" : \"SUCCESS\"}")
259 @ApiResponse(code=400, message = "Failure",examples = @Example( value = {
260 @ExampleProperty(mediaType="application/json",value =
261 "{\"error\" : \"<errorMessage>\","
262 + "\"status\" : \"FAILURE\"}")
265 public Response dropKeySpace(
266 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
267 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
268 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
269 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
270 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
271 @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
272 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception {
274 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
275 EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) ");
276 logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName);
277 if (MusicUtil.isKeyspaceActive()) {
278 String consistency = MusicUtil.EVENTUAL;// for now this needs only
279 PreparedQueryObject queryObject = new PreparedQueryObject();
280 queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
281 String droperror = "Error Deleteing Keyspace " + keyspaceName;
283 ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
284 if ( result.equals(ResultType.FAILURE) ) {
285 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError(droperror).toMap()).build();
287 } catch ( MusicQueryException ex) {
288 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.QUERYERROR
289 ,ErrorSeverity.WARN, ErrorTypes.QUERYERROR);
290 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(droperror + " " + ex.getMessage()).toMap()).build();
291 } catch ( MusicServiceException ex) {
292 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR
293 ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex);
294 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(droperror + " " + ex.getMessage()).toMap()).build();
296 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build();
298 String vError = "Keyspace deletion has been turned off. Contact DBA to delete the keyspace or set keyspace.active to true.";
299 logger.info(EELFLoggerDelegate.applicationLogger,vError);
300 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
301 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
304 EELFLoggerDelegate.mdcRemove("keyspace");
316 * @throws Exception -
319 @Path("/{keyspace: .*}/tables/{tablename: .*}")
320 @ApiOperation(value = "Create Table", response = String.class,
321 notes = "Create a table with the required json in the body.")
322 @Consumes(MediaType.APPLICATION_JSON)
323 @Produces(MediaType.APPLICATION_JSON)
324 @ApiResponses(value={
325 @ApiResponse(code=200, message = "Success",examples = @Example( value = {
326 @ExampleProperty(mediaType="application/json",value =
327 "{\"message\" : \"Tablename <tablename> Created under keyspace <keyspace>\","
328 + "\"status\" : \"SUCCESS\"}")
330 @ApiResponse(code=400, message = "Failure",examples = @Example( value = {
331 @ExampleProperty(mediaType="application/json",value =
332 "{\"error\" : \"<errorMessage>\","
333 + "\"status\" : \"FAILURE\"}")
336 public Response createTable(
337 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
338 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
339 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
340 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
341 @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
342 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
344 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
345 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename) throws Exception {
347 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
348 if ( null == tableObj ) {
349 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
350 .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
352 if(keyspace == null || keyspace.isEmpty() || tablename == null || tablename.isEmpty()){
353 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
354 .setError("One or more path parameters are not set, please check and try again."
355 + "Parameter values: keyspace='" + keyspace + "' tablename='" + tablename + "'")
358 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
359 String consistency = MusicUtil.EVENTUAL;
360 // for now this needs only eventual consistency
361 String primaryKey = null;
362 String partitionKey = tableObj.getPartitionKey();
363 String clusterKey = tableObj.getClusteringKey();
364 String filteringKey = tableObj.getFilteringKey();
365 if(filteringKey != null) {
366 clusterKey = clusterKey + "," + filteringKey;
368 primaryKey = tableObj.getPrimaryKey(); // get primaryKey if available
370 PreparedQueryObject queryObject = new PreparedQueryObject();
371 // first read the information about the table fields
372 Map<String, String> fields = tableObj.getFields();
373 if (fields == null) {
374 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
375 .setError("Create Table Error: No fields in request").toMap()).build();
378 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
380 for (Map.Entry<String, String> entry : fields.entrySet()) {
381 if (entry.getKey().equals("PRIMARY KEY")) {
382 primaryKey = entry.getValue(); // replaces primaryKey
383 primaryKey = primaryKey.trim();
385 if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
386 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
389 if (counter != (fields.size() - 1) ) {
390 counter = counter + 1;
393 if((primaryKey != null) && (partitionKey == null)) {
394 primaryKey = primaryKey.trim();
395 int count1 = StringUtils.countMatches(primaryKey, ')');
396 int count2 = StringUtils.countMatches(primaryKey, '(');
397 if (count1 != count2) {
398 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
399 .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey)
403 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) {
404 if (primaryKey.contains(",") ) {
405 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
406 partitionKey=partitionKey.replaceAll("[\\(]+","");
407 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
408 clusterKey=clusterKey.replaceAll("[)]+", "");
410 partitionKey=primaryKey;
411 partitionKey=partitionKey.replaceAll("[\\)]+","");
412 partitionKey=partitionKey.replaceAll("[\\(]+","");
415 } else { // not null and has ) before the last char
416 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
417 partitionKey=partitionKey.replaceAll("[\\(]+","");
418 partitionKey = partitionKey.trim();
419 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
420 clusterKey=clusterKey.replaceAll("[\\(]+","");
421 clusterKey=clusterKey.replaceAll("[\\)]+","");
422 clusterKey = clusterKey.trim();
423 if (clusterKey.indexOf(',') == 0) {
424 clusterKey=clusterKey.substring(1);
426 clusterKey = clusterKey.trim();
427 if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),)
430 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
431 && (partitionKey.equalsIgnoreCase(clusterKey) ||
432 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
433 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
434 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
435 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
436 + " primary key=" + primaryKey)
441 if (partitionKey.isEmpty() ) primaryKey="";
442 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
443 else primaryKey=" (" + partitionKey + ")," + clusterKey;
446 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
448 } else { // end of length > 0
450 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
451 && (partitionKey.equalsIgnoreCase(clusterKey) ||
452 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
453 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
454 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
455 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
459 if (partitionKey.isEmpty() ) primaryKey="";
460 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
461 else primaryKey=" (" + partitionKey + ")," + clusterKey;
463 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
465 fieldsString.append(")");
467 } // end of last field check
470 // information about the name-value style properties
471 Map<String, Object> propertiesMap = tableObj.getProperties();
472 StringBuilder propertiesString = new StringBuilder();
473 if (propertiesMap != null) {
475 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
476 Object ot = entry.getValue();
477 String value = ot + "";
478 if (ot instanceof String) {
479 value = "'" + value + "'";
480 } else if (ot instanceof Map) {
481 @SuppressWarnings("unchecked")
482 Map<String, Object> otMap = (Map<String, Object>) ot;
483 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
486 propertiesString.append(entry.getKey() + "=" + value + "");
487 if (counter != propertiesMap.size() - 1)
488 propertiesString.append(" AND ");
490 counter = counter + 1;
494 String clusteringOrder = tableObj.getClusteringOrder();
496 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
497 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
499 for (int i = 0; i < arrayClusterOrder.length; i++) {
500 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
501 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
504 return response.status(Status.BAD_REQUEST)
505 .entity(new JsonResponse(ResultType.FAILURE)
506 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
509 // add validation for column names in cluster key
512 if (!(clusterKey.isEmpty())) {
513 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
514 //cjc check if propertiesString.length() >0 instead propertiesMap
515 if (propertiesMap != null) {
516 propertiesString.append(" AND "+ clusteringOrder);
518 propertiesString.append(clusteringOrder);
521 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
525 queryObject.appendQueryString(
526 "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
529 if (propertiesString != null && propertiesString.length()>0 )
530 queryObject.appendQueryString(" WITH " + propertiesString);
531 queryObject.appendQueryString(";");
532 ResultType result = ResultType.FAILURE;
534 result = MusicCore.createTable(keyspace, tablename, queryObject, consistency);
535 } catch (MusicServiceException ex) {
536 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR);
537 response.status(Status.BAD_REQUEST);
538 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
540 if ( result.equals(ResultType.FAILURE) ) {
541 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build();
543 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename.trim() + " Created under keyspace " + keyspace.trim()).toMap()).build();
545 EELFLoggerDelegate.mdcRemove("keyspace");
558 @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}")
559 @ApiOperation(value = "Create Index", response = String.class,
560 notes = "An index provides a means to access data using attributes "
561 + "other than the partition key. The benefit is fast, efficient lookup "
562 + "of data matching a given condition.")
563 @Produces(MediaType.APPLICATION_JSON)
564 @ApiResponses(value={
565 @ApiResponse(code=200, message = "Success",examples = @Example( value = {
566 @ExampleProperty(mediaType="application/json",value =
567 "{\"message\" : \"Index Created on <keyspace>.<table>.<field>\","
568 + "\"status\" : \"SUCCESS\"}")
570 @ApiResponse(code=400, message = "Failure",examples = @Example( value = {
571 @ExampleProperty(mediaType="application/json",value =
572 "{\"error\" : \"<errorMessage>\","
573 + "\"status\" : \"FAILURE\"}")
575 @ApiResponse(code=400, message = "Failure",examples = @Example( value = {
576 @ExampleProperty(mediaType="application/json",value =
577 "{\"error\" : \"Unknown Error in create index.\","
578 + "\"status\" : \"FAILURE\"}")
581 public Response createIndex(
582 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
583 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
584 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
585 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
586 @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
587 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
588 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
589 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename,
590 @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName,
591 @Context UriInfo info) throws Exception {
593 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
594 if ((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.isEmpty())){
595 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
596 .setError("one or more path parameters are not set, please check and try again")
599 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
600 MultivaluedMap<String, String> rowParams = info.getQueryParameters();
601 String indexName = "";
602 if (rowParams.getFirst("index_name") != null)
603 indexName = rowParams.getFirst("index_name");
604 PreparedQueryObject query = new PreparedQueryObject();
605 query.appendQueryString("Create index if not exists " + indexName + " on " + keyspace + "."
606 + tablename + " (" + fieldName + ");");
608 ResultType result = ResultType.FAILURE;
610 result = MusicCore.nonKeyRelatedPut(query, "eventual");
611 } catch (MusicServiceException ex) {
612 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity
613 .CRITICAL, ErrorTypes.GENERALSERVICEERROR, ex);
614 response.status(Status.BAD_REQUEST);
615 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
617 if ( result.equals(ResultType.SUCCESS) ) {
618 return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build();
620 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build();
623 EELFLoggerDelegate.mdcRemove("keyspace");
636 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
637 @ApiOperation(value = "Insert Into Table", response = String.class,
638 notes = "Insert into table with data in json body.")
639 @Consumes(MediaType.APPLICATION_JSON)
640 @Produces(MediaType.APPLICATION_JSON)
641 @ApiResponses(value={
642 @ApiResponse(code=200, message = "Success",examples = @Example( value = {
643 @ExampleProperty(mediaType="application/json",value =
644 "{\"message\" : \"Insert Successful\","
645 + "\"status\" : \"SUCCESS\"}")
647 @ApiResponse(code=400, message = "Failure - Generic",examples = @Example( value = {
648 @ExampleProperty(mediaType="application/json",value =
649 "{\"error\" : \"<errorMessage>\","
650 + "\"status\" : \"FAILURE\"}")
653 public Response insertIntoTable(
654 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
655 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
656 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
657 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
658 @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
659 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
661 @ApiParam(value = "Keyspace Name",
662 required = true) @PathParam("keyspace") String keyspace,
663 @ApiParam(value = "Table Name",
664 required = true) @PathParam("tablename") String tablename) {
666 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
667 if ( null == insObj ) {
668 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
669 .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
671 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
672 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
673 .setError("one or more path parameters are not set, please check and try again")
676 EELFLoggerDelegate.mdcPut("keyspace","(" + keyspace + ")");
677 PreparedQueryObject queryObject = new PreparedQueryObject();
678 TableMetadata tableInfo = null;
680 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
681 if(tableInfo == null) {
682 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build();
684 } catch (MusicServiceException e) {
685 logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
686 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
688 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
689 StringBuilder fieldsString = new StringBuilder("(vector_ts,");
691 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
692 StringBuilder valueString = new StringBuilder("(" + "?" + ",");
693 queryObject.addValue(vectorTs);
695 Map<String, Object> valuesMap = insObj.getValues();
696 if (valuesMap==null) {
697 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
698 .setError("Nothing to insert. No values provided in request.").toMap()).build();
701 String primaryKey = "";
702 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
703 fieldsString.append("" + entry.getKey());
704 Object valueObj = entry.getValue();
705 if (primaryKeyName.equals(entry.getKey())) {
706 primaryKey = entry.getValue() + "";
707 primaryKey = primaryKey.replace("'", "''");
709 DataType colType = null;
711 colType = tableInfo.getColumn(entry.getKey()).getType();
712 } catch(NullPointerException ex) {
713 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey
714 (), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex);
715 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
718 Object formattedValue = null;
720 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
721 } catch (Exception e) {
722 logger.error(EELFLoggerDelegate.errorLogger,e);
724 valueString.append("?");
726 queryObject.addValue(formattedValue);
728 if (counter == valuesMap.size() - 1) {
729 fieldsString.append(")");
730 valueString.append(")");
732 fieldsString.append(",");
733 valueString.append(",");
735 counter = counter + 1;
739 Map<String, byte[]> objectMap = insObj.getObjectMap();
740 if(objectMap != null) {
741 for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) {
743 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ",");
744 valueString.replace(valueString.length()-1, valueString.length(), ",");
746 fieldsString.append("" + entry.getKey());
747 byte[] valueObj = entry.getValue();
748 if (primaryKeyName.equals(entry.getKey())) {
749 primaryKey = entry.getValue() + "";
750 primaryKey = primaryKey.replace("'", "''");
752 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
753 ByteBuffer formattedValue = null;
754 if(colType.toString().toLowerCase().contains("blob")) {
755 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
757 valueString.append("?");
758 queryObject.addValue(formattedValue);
759 counter = counter + 1;
760 fieldsString.append(",");
761 valueString.append(",");
765 if(primaryKey == null || primaryKey.length() <= 0) {
766 logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName );
767 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build();
770 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")");
771 valueString.replace(valueString.length()-1, valueString.length(), ")");
773 queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
774 + fieldsString + " VALUES " + valueString);
776 String ttl = insObj.getTtl();
777 String timestamp = insObj.getTimestamp();
779 if ((ttl != null) && (timestamp != null)) {
780 logger.info(EELFLoggerDelegate.applicationLogger, "both there");
781 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
782 queryObject.addValue(Integer.parseInt(ttl));
783 queryObject.addValue(Long.parseLong(timestamp));
786 if ((ttl != null) && (timestamp == null)) {
787 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
788 queryObject.appendQueryString(" USING TTL ?");
789 queryObject.addValue(Integer.parseInt(ttl));
792 if ((ttl == null) && (timestamp != null)) {
793 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
794 queryObject.appendQueryString(" USING TIMESTAMP ?");
795 queryObject.addValue(Long.parseLong(timestamp));
798 queryObject.appendQueryString(";");
800 ReturnType result = null;
801 String consistency = insObj.getConsistencyInfo().get("type");
802 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) {
803 if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency"))) {
804 queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency"));
806 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
809 queryObject.setOperation("insert");
811 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
812 result = MusicCore.eventualPut(queryObject);
813 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
814 String lockId = insObj.getConsistencyInfo().get("lockId");
816 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
817 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
818 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
819 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
821 result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null);
822 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
823 result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null);
825 } catch (Exception ex) {
826 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity
827 .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
828 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
831 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
832 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
833 }else if(result.getResult() == ResultType.FAILURE) {
834 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build();
836 return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build();
838 EELFLoggerDelegate.mdcRemove("keyspace");
849 * @throws MusicServiceException
850 * @throws MusicQueryException
854 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
855 @ApiOperation(value = "Update Table", response = String.class,
856 notes = "Update the table with the data in the JSON body.")
857 @Consumes(MediaType.APPLICATION_JSON)
858 @Produces(MediaType.APPLICATION_JSON)
859 public Response updateTable(
860 @ApiParam(value = "Major Version",
861 required = true) @PathParam("version") String version,
862 @ApiParam(value = "Minor Version",
863 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
864 @ApiParam(value = "Patch Version",
865 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
866 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
867 @ApiParam(value = "Application namespace",
868 required = false, hidden = true) @HeaderParam(NS) String ns,
869 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
870 JsonUpdate updateObj,
871 @ApiParam(value = "Keyspace Name",
872 required = true) @PathParam("keyspace") String keyspace,
873 @ApiParam(value = "Table Name",
874 required = true) @PathParam("tablename") String tablename,
875 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
877 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
878 if ( null == updateObj ) {
879 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
880 .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
882 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
883 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
884 .setError("one or more path parameters are not set, please check and try again")
887 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
888 long startTime = System.currentTimeMillis();
889 String operationId = UUID.randomUUID().toString(); // just for infoging
891 String consistency = updateObj.getConsistencyInfo().get("type");
893 logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
894 + " update-" + operationId + "-------------------------");
895 // obtain the field value pairs of the update
897 PreparedQueryObject queryObject = new PreparedQueryObject();
898 Map<String, Object> valuesMap = updateObj.getValues();
900 TableMetadata tableInfo;
902 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
903 } catch (MusicServiceException e) {
904 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
905 .GENERALSERVICEERROR, e);
906 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
908 if (tableInfo == null) {
909 logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
910 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
911 .setError("Table information not found. Please check input for table name= "
912 + keyspace + "." + tablename).toMap()).build();
914 String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
915 StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
916 queryObject.addValue(vectorTs);
918 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
919 Object valueObj = entry.getValue();
920 DataType colType = null;
922 colType = tableInfo.getColumn(entry.getKey()).getType();
923 } catch(NullPointerException ex) {
924 logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey(), ex);
925 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
927 Object valueString = null;
929 valueString = MusicUtil.convertToActualDataType(colType, valueObj);
930 } catch (Exception e) {
931 logger.error(EELFLoggerDelegate.errorLogger,e);
933 fieldValueString.append(entry.getKey() + "= ?");
934 queryObject.addValue(valueString);
935 if (counter != valuesMap.size() - 1) {
936 fieldValueString.append(",");
938 counter = counter + 1;
940 String ttl = updateObj.getTtl();
941 String timestamp = updateObj.getTimestamp();
943 queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " ");
944 if ((ttl != null) && (timestamp != null)) {
945 logger.info("both there");
946 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
947 queryObject.addValue(Integer.parseInt(ttl));
948 queryObject.addValue(Long.parseLong(timestamp));
951 if ((ttl != null) && (timestamp == null)) {
952 logger.info("ONLY TTL there");
953 queryObject.appendQueryString(" USING TTL ?");
954 queryObject.addValue(Integer.parseInt(ttl));
957 if ((ttl == null) && (timestamp != null)) {
958 logger.info("ONLY timestamp there");
959 queryObject.appendQueryString(" USING TIMESTAMP ?");
960 queryObject.addValue(Long.parseLong(timestamp));
962 // get the row specifier
963 RowIdentifier rowId = null;
965 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
966 if(rowId == null || rowId.primarKeyValue.isEmpty()) {
967 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
968 .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();
970 } catch (MusicServiceException ex) {
971 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
972 .GENERALSERVICEERROR, ex);
973 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
976 queryObject.appendQueryString(
977 " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";");
979 // get the conditional, if any
980 Condition conditionInfo;
981 if (updateObj.getConditions() == null) {
982 conditionInfo = null;
984 // to avoid parsing repeatedly, just send the select query to obtain row
985 PreparedQueryObject selectQuery = new PreparedQueryObject();
986 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
987 + rowId.rowIdString + ";");
988 selectQuery.addValue(rowId.primarKeyValue);
989 conditionInfo = new Condition(updateObj.getConditions(), selectQuery);
992 ReturnType operationResult = null;
993 long jsonParseCompletionTime = System.currentTimeMillis();
995 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) {
996 if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency"))) {
997 queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency"));
999 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1002 queryObject.setOperation("update");
1003 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
1004 operationResult = MusicCore.eventualPut(queryObject);
1005 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1006 String lockId = updateObj.getConsistencyInfo().get("lockId");
1007 if(lockId == null) {
1008 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1009 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1010 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1011 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1014 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1015 queryObject, lockId, conditionInfo);
1016 } catch ( Exception e) {
1017 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN,
1018 ErrorTypes.GENERALSERVICEERROR, e);
1019 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Error doing critical put: " + e.getMessage()).toMap()).build();
1021 } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) {
1022 // this function is mainly for the benchmarks
1024 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename,
1025 rowId.primarKeyValue, queryObject, conditionInfo);
1026 } catch (MusicLockingException e) {
1027 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN,
1028 ErrorTypes.GENERALSERVICEERROR, e);
1029 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1031 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1033 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1034 queryObject, conditionInfo);
1035 } catch (MusicLockingException e) {
1036 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e);
1037 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1039 } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1040 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1042 long actualUpdateCompletionTime = System.currentTimeMillis();
1044 long endTime = System.currentTimeMillis();
1045 String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
1046 + ":" + "|total operation time:" + (endTime - startTime)
1047 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
1048 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
1051 if (operationResult != null && operationResult.getTimingInfo() != null) {
1052 String lockManagementTime = operationResult.getTimingInfo();
1053 timingString = timingString + lockManagementTime;
1055 logger.info(EELFLoggerDelegate.applicationLogger, timingString);
1057 if (operationResult==null) {
1058 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1059 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1061 if ( operationResult.getResult() == ResultType.SUCCESS ) {
1062 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1064 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1065 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build();
1068 EELFLoggerDelegate.mdcRemove("keyspace");
1079 * @throws MusicServiceException
1080 * @throws MusicQueryException
1084 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1085 @ApiOperation(value = "Delete From table", response = String.class,
1086 notes = "Delete from a table, the row or parts of a row. Based on JSON body.")
1087 @Consumes(MediaType.APPLICATION_JSON)
1088 @Produces(MediaType.APPLICATION_JSON)
1089 public Response deleteFromTable(
1090 @ApiParam(value = "Major Version",
1091 required = true) @PathParam("version") String version,
1092 @ApiParam(value = "Minor Version",
1093 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1094 @ApiParam(value = "Patch Version",
1095 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1096 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
1097 @ApiParam(value = "Application namespace",
1098 required = false, hidden = true) @HeaderParam(NS) String ns,
1099 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1101 @ApiParam(value = "Keyspace Name",
1102 required = true) @PathParam("keyspace") String keyspace,
1103 @ApiParam(value = "Table Name",
1104 required = true) @PathParam("tablename") String tablename,
1105 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
1107 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1108 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1109 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1110 .setError("one or more path parameters are not set, please check and try again")
1113 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1114 if(delObj == null) {
1115 logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult(), AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
1116 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
1118 PreparedQueryObject queryObject = new PreparedQueryObject();
1119 StringBuilder columnString = new StringBuilder();
1122 List<String> columnList = delObj.getColumns();
1123 if (columnList != null) {
1124 for (String column : columnList) {
1125 columnString.append(column);
1126 if (counter != columnList.size() - 1)
1127 columnString.append(",");
1128 counter = counter + 1;
1132 // get the row specifier
1133 RowIdentifier rowId = null;
1135 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1136 } catch (MusicServiceException ex) {
1137 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
1138 .GENERALSERVICEERROR, ex);
1139 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1141 String rowSpec = rowId.rowIdString.toString();
1143 if ((columnList != null) && (!rowSpec.isEmpty())) {
1144 queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "."
1145 + tablename + " WHERE " + rowSpec + ";");
1148 if ((columnList == null) && (!rowSpec.isEmpty())) {
1149 queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE "
1153 if ((columnList != null) && (rowSpec.isEmpty())) {
1154 queryObject.appendQueryString(
1155 "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";");
1157 // get the conditional, if any
1158 Condition conditionInfo;
1159 if (delObj.getConditions() == null) {
1160 conditionInfo = null;
1162 // to avoid parsing repeatedly, just send the select query to
1164 PreparedQueryObject selectQuery = new PreparedQueryObject();
1165 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1166 + rowId.rowIdString + ";");
1167 selectQuery.addValue(rowId.primarKeyValue);
1168 conditionInfo = new Condition(delObj.getConditions(), selectQuery);
1171 String consistency = delObj.getConsistencyInfo().get("type");
1174 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) {
1175 if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency"))) {
1176 queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency"));
1178 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR)
1179 .setError("Invalid Consistency type").toMap()).build();
1182 ReturnType operationResult = null;
1183 queryObject.setOperation("delete");
1185 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1186 operationResult = MusicCore.eventualPut(queryObject);
1187 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1188 String lockId = delObj.getConsistencyInfo().get("lockId");
1189 if(lockId == null) {
1190 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1191 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1192 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1193 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1195 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1196 queryObject, lockId, conditionInfo);
1197 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1198 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1199 queryObject, conditionInfo);
1200 } else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1201 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1203 } catch (MusicLockingException e) {
1204 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e);
1205 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1206 .setError("Unable to perform Delete operation. Exception from music").toMap()).build();
1208 if (operationResult==null) {
1209 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1210 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1212 if (operationResult.getResult().equals(ResultType.SUCCESS)) {
1213 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1215 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1216 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build();
1219 EELFLoggerDelegate.mdcRemove("keyspace");
1231 @Path("/{keyspace: .*}/tables/{tablename: .*}")
1232 @ApiOperation(value = "Drop Table", response = String.class)
1233 @Produces(MediaType.APPLICATION_JSON)
1234 @ApiResponses(value={
1235 @ApiResponse(code=200, message = "Success",examples = @Example( value = {
1236 @ExampleProperty(mediaType="application/json",value =
1237 "{\"status\" : \"SUCCESS\"}")
1239 @ApiResponse(code=400, message = "Failure",examples = @Example( value = {
1240 @ExampleProperty(mediaType="application/json",value =
1241 "{\"error\" : \"<errorMessage>\","
1242 + "\"status\" : \"FAILURE\"}")
1245 public Response dropTable(
1246 @ApiParam(value = "Major Version",
1247 required = true) @PathParam("version") String version,
1248 @ApiParam(value = "Minor Version",
1249 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1250 @ApiParam(value = "Patch Version",
1251 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1252 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
1253 @ApiParam(value = "Application namespace",
1254 required = false, hidden = true) @HeaderParam(NS) String ns,
1255 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1256 @ApiParam(value = "Keyspace Name",
1257 required = true) @PathParam("keyspace") String keyspace,
1258 @ApiParam(value = "Table Name",
1259 required = true) @PathParam("tablename") String tablename) throws Exception {
1261 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1262 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1263 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1264 .setError("one or more path parameters are not set, please check and try again")
1267 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1268 String consistency = "eventual";// for now this needs only eventual consistency
1269 PreparedQueryObject query = new PreparedQueryObject();
1270 query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";");
1272 return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build();
1273 } catch (MusicQueryException ex) {
1274 logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.WARN
1275 , ErrorTypes.QUERYERROR);
1276 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1277 } catch (MusicServiceException ex) {
1278 logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN
1279 , ErrorTypes.GENERALSERVICEERROR,ex);
1280 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1283 EELFLoggerDelegate.mdcRemove("keyspace");
1296 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget")
1297 @ApiOperation(value = "** Depreciated ** - Select Critical", response = Map.class,
1298 notes = "This API is depreciated in favor of the regular select api.\n"
1299 + "Avaliable to use with the select api by providing a minorVersion of 1 "
1300 + "and patchVersion of 0.\n"
1301 + "Critical Get requires parameter rowId=value and consistency in order to work.\n"
1302 + "It will fail if either are missing.")
1303 @Consumes(MediaType.APPLICATION_JSON)
1304 @Produces(MediaType.APPLICATION_JSON)
1305 @ApiResponses(value={
1306 @ApiResponse(code=200, message = "Success",examples = @Example( value = {
1307 @ExampleProperty(mediaType="application/json",value =
1308 "{\"result\":{\"row 0\":{\"address\":"
1309 + "{\"city\":\"Someplace\",\"street\":\"1 Some way\"},"
1310 + "\"emp_salary\":50,\"emp_name\":\"tom\",\"emp_id\":"
1311 + "\"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\"}},\"status\":\"SUCCESS\"}")
1313 @ApiResponse(code=400, message = "Failure",examples = @Example( value = {
1314 @ExampleProperty(mediaType="application/json",value =
1315 "{\"error\" : \"<errorMessage>\","
1316 + "\"status\" : \"FAILURE\"}")
1319 public Response selectCritical(
1320 @ApiParam(value = "Major Version",
1321 required = true) @PathParam("version") String version,
1322 @ApiParam(value = "Minor Version",example = "0",
1323 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1324 @ApiParam(value = "Patch Version",example = "0",
1325 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1326 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
1327 @ApiParam(value = "Application namespace",
1328 required = false, hidden = true) @HeaderParam(NS) String ns,
1329 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1331 @ApiParam(value = "Keyspace Name",
1332 required = true) @PathParam("keyspace") String keyspace,
1333 @ApiParam(value = "Table Name",
1334 required = true) @PathParam("tablename") String tablename,
1335 @Context UriInfo info) throws Exception {
1337 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1338 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())) {
1339 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1340 .setError("one or more path parameters are not set, please check and try again")
1343 EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " )");
1344 if (info.getQueryParameters().isEmpty()) {
1345 logger.error(EELFLoggerDelegate.errorLogger,RestMusicDataAPI.PARAMETER_ERROR, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
1346 .GENERALSERVICEERROR);
1347 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(RestMusicDataAPI.PARAMETER_ERROR).toMap()).build();
1349 if (selObj == null || selObj.getConsistencyInfo().isEmpty()) {
1350 String error = " Missing Body or Consistency type.";
1351 logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult() + error, AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
1352 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult() + error).toMap()).build();
1355 String lockId = selObj.getConsistencyInfo().get("lockId");
1356 PreparedQueryObject queryObject = new PreparedQueryObject();
1357 RowIdentifier rowId = null;
1359 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1360 if ( "".equals(rowId)) {
1361 logger.error(EELFLoggerDelegate.errorLogger,RestMusicDataAPI.PARAMETER_ERROR, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
1362 .GENERALSERVICEERROR);
1363 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(RestMusicDataAPI.PARAMETER_ERROR).toMap()).build();
1365 } catch (MusicServiceException ex) {
1366 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
1367 .GENERALSERVICEERROR, ex);
1368 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1370 queryObject.appendQueryString(
1371 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";");
1373 ResultSet results = null;
1375 String consistency = selObj.getConsistencyInfo().get("type");
1377 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1378 if(lockId == null) {
1379 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1380 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1381 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1382 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1384 results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,lockId);
1385 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1386 results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
1388 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1389 .setError("Consistency must be: " + MusicUtil.ATOMIC + " or " + MusicUtil.CRITICAL)
1392 } catch ( MusicLockingException | MusicServiceException me ) {
1393 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Music Exception" + me.getMessage()).toMap()).build();
1394 } catch ( Exception ex) {
1395 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1398 if(results!=null && results.getAvailableWithoutFetching() >0) {
1399 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1401 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build();
1403 EELFLoggerDelegate.mdcRemove("keyspace");
1408 * This API will replace the original select and provide a single API fro select and critical.
1409 * The idea is to depreciate the older api of criticalGet and use a single API.
1418 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1419 @ApiOperation(value = "Select", response = Map.class,
1420 notes = "This has 2 versions: if minorVersion and patchVersion is null or 0, this will be a Eventual Select only.\n"
1421 + "If minorVersion is 1 and patchVersion is 0, this will act like the Critical Select \n"
1422 + "Critical Get requires parameter rowId=value and consistency in order to work.\n"
1423 + "If parameters are missing or consistency information is missing. An eventual select will be preformed.")
1424 @Consumes(MediaType.APPLICATION_JSON)
1425 @Produces(MediaType.APPLICATION_JSON)
1426 @ApiResponses(value={
1427 @ApiResponse(code=200, message = "Success",examples = @Example( value = {
1428 @ExampleProperty(mediaType="application/json",value =
1429 "{\"result\":{\"row 0\":{\"address\":"
1430 + "{\"city\":\"Someplace\",\"street\":\"1 Some way\"},"
1431 + "\"emp_salary\":50,\"emp_name\":\"tom\",\"emp_id\":"
1432 + "\"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\"}},\"status\":\"SUCCESS\"}")
1434 @ApiResponse(code=400, message = "Failure",examples = @Example( value = {
1435 @ExampleProperty(mediaType="application/json",value =
1436 "{\"error\" : \"<errorMessage>\","
1437 + "\"status\" : \"FAILURE\"}")
1440 public Response selectWithCritical(
1441 @ApiParam(value = "Major Version",example = "v2",
1442 required = true) @PathParam("version") String version,
1443 @ApiParam(value = "Minor Version",example = "1",
1444 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1445 @ApiParam(value = "Patch Version",example = "0",
1446 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1447 @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
1448 @ApiParam(value = "Application namespace",
1449 required = false,hidden = true) @HeaderParam(NS) String ns,
1450 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1452 @ApiParam(value = "Keyspace Name", required = true) @PathParam("keyspace") String keyspace,
1453 @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename,
1454 @Context UriInfo info) throws Exception {
1455 if ((minorVersion != null && patchVersion != null) &&
1456 (Integer.parseInt(minorVersion) == 1 && Integer.parseInt(patchVersion) == 0) &&
1457 (!(null == selObj) && !selObj.getConsistencyInfo().isEmpty())) {
1458 return selectCritical(version, minorVersion, patchVersion, aid, ns, authorization, selObj, keyspace, tablename, info);
1460 return select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info);
1472 private Response select(
1473 String version,String minorVersion,String patchVersion,
1474 String aid,String ns,String authorization,String keyspace,
1475 String tablename,UriInfo info) throws Exception {
1477 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1478 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1479 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1480 .setError("one or more path parameters are not set, please check and try again")
1483 EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " ) ");
1484 PreparedQueryObject queryObject = new PreparedQueryObject();
1486 if (info.getQueryParameters().isEmpty()) { // select all
1487 queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";");
1489 int limit = -1; // do not limit the number of results
1491 queryObject = selectSpecificQuery(keyspace, tablename, info, limit);
1492 } catch (MusicServiceException ex) {
1493 logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN,
1494 ErrorTypes.GENERALSERVICEERROR, ex);
1495 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1499 ResultSet results = MusicCore.get(queryObject);
1500 if(results.getAvailableWithoutFetching() >0) {
1501 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1503 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build();
1504 } catch (MusicServiceException ex) {
1505 logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR,
1506 ErrorTypes.MUSICSERVICEERROR, ex);
1507 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1510 EELFLoggerDelegate.mdcRemove("keyspace");
1521 * @throws MusicServiceException
1523 public PreparedQueryObject selectSpecificQuery(String keyspace,
1524 String tablename, UriInfo info, int limit)
1525 throws MusicServiceException {
1526 PreparedQueryObject queryObject = new PreparedQueryObject();
1527 StringBuilder rowIdString = getRowIdentifier(keyspace,
1528 tablename,info.getQueryParameters(),queryObject).rowIdString;
1529 queryObject.appendQueryString(
1530 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1532 queryObject.appendQueryString(" LIMIT " + limit);
1534 queryObject.appendQueryString(";");
1543 * @param queryObject
1545 * @throws MusicServiceException
1547 private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1548 MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1549 throws MusicServiceException {
1550 StringBuilder rowSpec = new StringBuilder();
1552 TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
1553 if (tableInfo == null) {
1554 logger.error(EELFLoggerDelegate.errorLogger,
1555 "Table information not found. Please check input for table name= "
1556 + keyspace + "." + tablename);
1557 throw new MusicServiceException(
1558 "Table information not found. Please check input for table name= "
1559 + keyspace + "." + tablename);
1561 StringBuilder primaryKey = new StringBuilder();
1562 for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1563 String keyName = entry.getKey();
1564 List<String> valueList = entry.getValue();
1565 String indValue = valueList.get(0);
1566 DataType colType = null;
1567 Object formattedValue = null;
1569 colType = tableInfo.getColumn(entry.getKey()).getType();
1570 formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1571 } catch (Exception e) {
1572 logger.error(EELFLoggerDelegate.errorLogger,e);
1574 if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) {
1575 primaryKey.append(indValue);
1577 rowSpec.append(keyName + "= ?");
1578 queryObject.addValue(formattedValue);
1579 if (counter != rowParams.size() - 1) {
1580 rowSpec.append(" AND ");
1582 counter = counter + 1;
1584 return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);