From c79755d43c123176515e5cafbba0774a03d297d3 Mon Sep 17 00:00:00 2001 From: "Nelson, Thomas (tn1381)" Date: Mon, 27 Aug 2018 19:52:13 +0000 Subject: Swagger Update and other updates. Updates related to callback api Change-Id: I2a4c00e8db4a430c5998e7770389451610f0770a Issue-ID: MUSIC-97 Signed-off-by: Nelson, Thomas (tn1381) --- docs/swagger.json | 42 ++-- examples/VotingApp/dependency-reduced-pom.xml | 38 +++ examples/VotingApp/pom.xml | 58 +++-- musictrigger/src/MusicTrigger.java | 38 ++- pom.xml | 2 +- .../jsonobjects/JSONCallbackResponse.java | 9 + .../datastore/jsonobjects/JsonNotification.java | 9 +- .../jsonobjects/JsonNotifyClientResponse.java | 61 +++++ src/main/java/org/onap/music/main/CachingUtil.java | 13 + src/main/java/org/onap/music/main/MusicUtil.java | 4 +- .../org/onap/music/main/PropertiesListener.java | 6 + .../org/onap/music/rest/RestMusicAdminAPI.java | 263 ++++++++++++++------- src/main/resources/logback.xml | 7 +- version.properties | 2 +- 14 files changed, 417 insertions(+), 135 deletions(-) create mode 100644 examples/VotingApp/dependency-reduced-pom.xml create mode 100644 src/main/java/org/onap/music/datastore/jsonobjects/JsonNotifyClientResponse.java mode change 100644 => 100755 version.properties diff --git a/docs/swagger.json b/docs/swagger.json index 3f4e220f..27db769f 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1001,29 +1001,18 @@ } } }, - "/v2/locks/acquire-with-lease/{lockreference}": { - "post": { + "/v2/locks/acquire/{lockreference}": { + "get": { "tags": [ "Lock Api" ], - "summary": "Aquire Lock with Lease", - "description": "", - "operationId": "accquireLockWithLease", - "consumes": [ - "application/json" - ], + "summary": "Aquire Lock", + "description": "Checks if the node is in the top of the queue and hence acquires the lock", + "operationId": "accquireLock", "produces": [ "application/json" ], "parameters": [ - { - "in": "body", - "name": "body", - "required": false, - "schema": { - "$ref": "#/definitions/JsonTable" - } - }, { "name": "lockreference", "in": "path", @@ -1080,18 +1069,29 @@ } } }, - "/v2/locks/acquire/{lockreference}": { - "get": { + "/v2/locks/acquire-with-lease/{lockreference}": { + "post": { "tags": [ "Lock Api" ], - "summary": "Aquire Lock", - "description": "Checks if the node is in the top of the queue and hence acquires the lock", - "operationId": "accquireLock", + "summary": "Aquire Lock with Lease", + "description": "", + "operationId": "accquireLockWithLease", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "parameters": [ + { + "in": "body", + "name": "body", + "required": false, + "schema": { + "$ref": "#/definitions/JsonTable" + } + }, { "name": "lockreference", "in": "path", diff --git a/examples/VotingApp/dependency-reduced-pom.xml b/examples/VotingApp/dependency-reduced-pom.xml new file mode 100644 index 00000000..faf90967 --- /dev/null +++ b/examples/VotingApp/dependency-reduced-pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + com.att.reserarch.VoteAppForMUSIC + VoteAppForMUSIC + 0.0.1-SNAPSHOT + + + + maven-shade-plugin + + + default-jar + package + + shade + + + + + + main.VotingApp + + + + + + + + + + + maven2-repository.java.net + Java.net Repository for Maven + http://download.java.net/maven/2/ + + + diff --git a/examples/VotingApp/pom.xml b/examples/VotingApp/pom.xml index 87cac6c0..0c85e60b 100644 --- a/examples/VotingApp/pom.xml +++ b/examples/VotingApp/pom.xml @@ -24,6 +24,7 @@ stated inside of the file. 4.0.0 com.att.reserarch.VoteAppForMUSIC VoteAppForMUSIC + jar 0.0.1-SNAPSHOT @@ -44,15 +45,15 @@ stated inside of the file. 1.9 - com.sun.jersey - jersey-json - 1.18.1 - - - com.owlike - genson - 0.99 - + com.sun.jersey + jersey-json + 1.18.1 + + + com.owlike + genson + 0.99 + com.sun.jersey jersey-client @@ -65,11 +66,11 @@ stated inside of the file. 1.9 - + com.googlecode.json-simple @@ -86,7 +87,36 @@ stated inside of the file. zookeeper 3.4.6 - + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.1 + - - \ No newline at end of file + + + + maven-shade-plugin + + + default-jar + package + + shade + + + + + + main.VotingApp + + + + + + + + + + diff --git a/musictrigger/src/MusicTrigger.java b/musictrigger/src/MusicTrigger.java index d70e41a0..b5894da1 100755 --- a/musictrigger/src/MusicTrigger.java +++ b/musictrigger/src/MusicTrigger.java @@ -25,6 +25,11 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Map; import javax.ws.rs.core.HttpHeaders; @@ -68,7 +73,6 @@ public class MusicTrigger implements ITrigger { boolean isInsert = checkQueryType(partition); org.json.simple.JSONObject obj = new org.json.simple.JSONObject(); - String operation = null; if(isDelete) operation = "delete"; @@ -76,14 +80,14 @@ public class MusicTrigger implements ITrigger { operation = "insert"; else operation = "update"; - Map changeMap = new HashMap<>(); + Map changeMap = new HashMap<>(); obj.put("operation", operation); obj.put("keyspace", ksName); obj.put("table_name", tableName); obj.put("full_table", ksName+"."+tableName); obj.put("primary_key", partition.metadata().getKeyValidator().getString(partition.partitionKey().getKey())); - + List updateList = new ArrayList<>(); //obj.put("message_id", partition.metadata().getKeyValidator().getString(partition.partitionKey().getKey())); if("update".equals(operation)) { try { @@ -97,15 +101,29 @@ public class MusicTrigger implements ITrigger { while(columns.hasNext()){ ColumnDefinition columnDef = columns.next(); Cell cell = cells.next(); - String data = new String(cell.value().array()); // If cell type is text + + String data = null; + if(cell.column().type.toString().equals("org.apache.cassandra.db.marshal.UTF8Type")) { + logger.info(">> type is String"); + data = new String(cell.value().array()); // If cell type is text + } else if(cell.column().type.toString().equals("org.apache.cassandra.db.marshal.Int32Type")) { + //ByteBuffer wrapped = ByteBuffer.wrap(cell.value()); // big-endian by default + int num = fromByteArray(cell.value().array()); + logger.info(">> type is Integer1 :: "+num); + data = String.valueOf(num); + } + logger.info("Inside triggers loop: "+columnDef.name+" : "+data); - changeMap.put(ksName+"."+tableName+"."+columnDef.name,data); + //changeMap.put(ksName+"."+tableName+"."+columnDef.name,data); + updateList.add(ksName+"."+tableName+":"+columnDef.name+":"+data); changeMap.put("field_value",ksName+"."+tableName+":"+columnDef.name+":"+data); + } } } catch (Exception e) { } + obj.put("updateList", updateList); } else { changeMap.put("field_value", ksName+"."+tableName); } @@ -121,6 +139,10 @@ public class MusicTrigger implements ITrigger { return Collections.emptyList(); } + private int fromByteArray(byte[] bytes) { + return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF); + } + private boolean checkQueryType(Partition partition) { UnfilteredRowIterator it = partition.unfilteredIterator(); while (it.hasNext()) { @@ -149,12 +171,12 @@ public class MusicTrigger implements ITrigger { .post(ClientResponse.class, data); if(response.getStatus() != 200){ - System.out.println("Exception..."); + System.out.println("Exception while notifying MUSIC..."); } - response.getHeaders().put(HttpHeaders.CONTENT_TYPE, Arrays.asList(MediaType.APPLICATION_JSON)); + /*response.getHeaders().put(HttpHeaders.CONTENT_TYPE, Arrays.asList(MediaType.APPLICATION_JSON)); response.bufferEntity(); String x = response.getEntity(String.class); - System.out.println("Response: "+x); + System.out.println("Response: "+x);*/ } diff --git a/pom.xml b/pom.xml index 15533ef2..5f686d21 100755 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ org.onap.music MUSIC war - 3.0.13-SNAPSHOT + 3.0.15-SNAPSHOT This is the MUSIC REST interface, packaged as a war file. diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JSONCallbackResponse.java b/src/main/java/org/onap/music/datastore/jsonobjects/JSONCallbackResponse.java index c521d0df..f869c342 100755 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JSONCallbackResponse.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JSONCallbackResponse.java @@ -22,6 +22,7 @@ package org.onap.music.datastore.jsonobjects; +import java.util.List; import java.util.Map; public class JSONCallbackResponse { @@ -33,6 +34,8 @@ public class JSONCallbackResponse { private String table_name; private String primary_key; private Object miscObjects; + private List updateList; + public String getFull_table() { return full_table; } @@ -75,6 +78,12 @@ public class JSONCallbackResponse { public Map getChangeValue() { return changeValue; } + public List getUpdateList() { + return updateList; + } + public void setUpdateList(List updateList) { + this.updateList = updateList; + } } diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonNotification.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonNotification.java index ad999190..1a8a93f5 100755 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonNotification.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonNotification.java @@ -44,7 +44,7 @@ public class JsonNotification implements Serializable { private String notify_insert; private String notify_delete; private String operation_type; - + private String triggerName; private Map response_body; public String getNotify_field() { @@ -101,7 +101,12 @@ public class JsonNotification implements Serializable { public void setOperation_type(String operation_type) { this.operation_type = operation_type; } - + public String getTriggerName() { + return triggerName; + } + public void setTriggerName(String triggerName) { + this.triggerName = triggerName; + } @Override public String toString() { try { diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonNotifyClientResponse.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonNotifyClientResponse.java new file mode 100644 index 00000000..f63625e7 --- /dev/null +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonNotifyClientResponse.java @@ -0,0 +1,61 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.datastore.jsonobjects; + +import java.io.Serializable; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "JsonNotifyClientResponse", description = "Json model for callback") +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonNotifyClientResponse implements Serializable { + private String message; + private String status; + + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + public String getStatus() { + return status; + } + public void setStatus(String status) { + this.status = status; + } + + @Override + public String toString() { + try { + return new com.fasterxml.jackson.databind.ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(this); + } catch (com.fasterxml.jackson.core.JsonProcessingException e) { + return message+ " : "+status; + } + + } + +} diff --git a/src/main/java/org/onap/music/main/CachingUtil.java b/src/main/java/org/onap/music/main/CachingUtil.java index 83b5158f..a4366836 100755 --- a/src/main/java/org/onap/music/main/CachingUtil.java +++ b/src/main/java/org/onap/music/main/CachingUtil.java @@ -21,10 +21,12 @@ */ package org.onap.music.main; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.UUID; import javax.ws.rs.core.HttpHeaders; @@ -67,6 +69,7 @@ public class CachingUtil implements Runnable { private static CacheAccess appNameCache = JCS.getInstance("appNameCache"); private static CacheAccess> musicValidateCache = JCS.getInstance("musicValidateCache"); private static CacheAccess callBackCache = JCS.getInstance("callBackCache"); + private static CacheAccess> callbackNotifyList = JCS.getInstance("callbackNotifyList"); private static Map userAttempts = new HashMap<>(); private static Map lastFailedTime = new HashMap<>(); @@ -77,6 +80,7 @@ public class CachingUtil implements Runnable { } public static void updateCallBackCache(String appName, JsonCallback jsonCallBack) { + logger.info("updateCallBackCache: updating cache....."); callBackCache.put(appName, jsonCallBack); } @@ -84,6 +88,15 @@ public class CachingUtil implements Runnable { return callBackCache.get(appName); } + public static void updateCallbackNotifyList(List notifyList) { + logger.info("callbackNotifyList: updating cache....."); + callbackNotifyList.put("callbackNotify", notifyList); + } + + public static List getCallbackNotifyList() { + return callbackNotifyList.get("callbackNotify"); + } + public void initializeMusicCache() { logger.info(EELFLoggerDelegate.applicationLogger,"Initializing Music Cache..."); musicCache.put("isInitialized", "true"); diff --git a/src/main/java/org/onap/music/main/MusicUtil.java b/src/main/java/org/onap/music/main/MusicUtil.java index 40d19766..5b23a935 100755 --- a/src/main/java/org/onap/music/main/MusicUtil.java +++ b/src/main/java/org/onap/music/main/MusicUtil.java @@ -615,10 +615,10 @@ public class MusicUtil { } - private static void setNotifyInterval(int notifyinterval) { + public static void setNotifyInterval(int notifyinterval) { MusicUtil.notifyinterval = notifyinterval; } - private static void setNotifyTimeOut(int notifytimeout) { + public static void setNotifyTimeOut(int notifytimeout) { MusicUtil.notifytimeout = notifytimeout; } diff --git a/src/main/java/org/onap/music/main/PropertiesListener.java b/src/main/java/org/onap/music/main/PropertiesListener.java index 0619cd41..0ed18be2 100755 --- a/src/main/java/org/onap/music/main/PropertiesListener.java +++ b/src/main/java/org/onap/music/main/PropertiesListener.java @@ -122,6 +122,12 @@ public class PropertiesListener implements ServletContextListener { case "cassandra.port": MusicUtil.setCassandraPort(Integer.parseInt(prop.getProperty(key))); break; + case "notify.interval": + MusicUtil.setNotifyInterval(Integer.parseInt(prop.getProperty(key))); + break; + case "notify.timeout": + MusicUtil.setNotifyTimeOut(Integer.parseInt(prop.getProperty(key))); + break; default: logger.error(EELFLoggerDelegate.errorLogger, "No case found for " + key); diff --git a/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java b/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java index e930e48b..48f28f8c 100755 --- a/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java @@ -24,9 +24,14 @@ package org.onap.music.rest; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.UUID; @@ -48,6 +53,7 @@ import org.onap.music.datastore.jsonobjects.JSONCallbackResponse; import org.onap.music.datastore.jsonobjects.JSONObject; import org.onap.music.datastore.jsonobjects.JsonCallback; import org.onap.music.datastore.jsonobjects.JsonNotification; +import org.onap.music.datastore.jsonobjects.JsonNotifyClientResponse; import org.onap.music.datastore.jsonobjects.JsonOnboard; import org.onap.music.eelf.logging.EELFLoggerDelegate; import org.onap.music.eelf.logging.format.AppMessages; @@ -79,8 +85,8 @@ import javax.ws.rs.core.MediaType; import com.datastax.driver.core.ColumnDefinitions; import com.datastax.driver.core.ColumnDefinitions.Definition; import com.datastax.driver.core.TableMetadata; -import java.util.Base64.Encoder; -import java.util.Base64.Decoder; +//import java.util.Base64.Encoder; +//import java.util.Base64.Decoder; @Path("/v2/admin") // @Path("/v{version: [0-9]+}/admin") @@ -135,7 +141,7 @@ public class RestMusicAdminAPI { MusicUtil.DEFAULTKEYSPACENAME)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt()))); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); @@ -396,7 +402,8 @@ public class RestMusicAdminAPI { } Client client = Client.create(); - + ObjectMapper mapper = new ObjectMapper(); + @POST @Path("/callbackOps") @Produces(MediaType.APPLICATION_JSON) @@ -417,25 +424,69 @@ public class RestMusicAdminAPI { Map resultMap = new HashMap<>(); try { - logger.info("Got notification: " + inputJsonObj.getData()); + logger.info(EELFLoggerDelegate.applicationLogger, "Got notification: " + inputJsonObj.getData()); String dataStr = inputJsonObj.getData(); - ObjectMapper mapper = new ObjectMapper(); JSONCallbackResponse jsonResponse = mapper.readValue(dataStr, JSONCallbackResponse.class); String operation = jsonResponse.getOperation(); Map changeValueMap = jsonResponse.getChangeValue(); String primaryKey = jsonResponse.getPrimary_key(); - //String full_table = jsonResponse.getFull_table(); //conductor.plans - String field_value = changeValueMap.get("field_value"); + String ksTableName = jsonResponse.getFull_table(); //conductor.plans + if(ksTableName.equals("admin.notification_master")) { + CachingUtil.updateCallbackNotifyList(new ArrayList()); + return Response.status(Status.OK).entity(resultMap).build(); + } + List inputUpdateList = jsonResponse.getUpdateList(); + /*String field_value = changeValueMap.get("field_value"); if(field_value == null) - field_value = jsonResponse.getFull_table(); - //Get from Cache - JsonCallback baseRequestObj = CachingUtil.getCallBackCache(field_value); - //baseRequestObj = null; - - if(baseRequestObj == null) { + field_value = jsonResponse.getFull_table();*/ + String field_value = null; + List notifiyList = CachingUtil.getCallbackNotifyList(); + if(notifiyList == null || notifiyList.isEmpty()) { logger.info("Is cache empty? reconstructing Object from cache.."); - baseRequestObj = constructJsonCallbackFromCache(field_value); + constructJsonCallbackFromCache(); + /*notifiyList = CachingUtil.getCallbackNotifyList(); + if("update".equals(operation)) { + List updateList = jsonResponse.getUpdateList(); + //logger.info("update list from trigger: "+updateList); + for(String element : updateList) { + logger.info("element: "+element); + logger.info("notifiyList: "+notifiyList); + if(notifiyList.contains(element)) { + logger.info("Found the notifyOn property: "+element); + field_value = element; + } + } + } + + baseRequestObj = CachingUtil.getCallBackCache(field_value); + logger.info("Reconstructing Object from cache is Successful.."+baseRequestObj);*/ } + notifiyList = CachingUtil.getCallbackNotifyList(); + JsonCallback baseRequestObj = null; + + if("update".equals(operation)) { + for(String element: inputUpdateList) { + baseRequestObj = CachingUtil.getCallBackCache(element); + if(baseRequestObj != null) { + logger.info("Found the element that was changed... "+element); + break; + } + } + + List updateList = jsonResponse.getUpdateList(); + //logger.info("update list from trigger: "+updateList); + for(String element : updateList) { + if(notifiyList.contains(element)) { + logger.info("Found the notifyOn property: "+element); + field_value = element; + break; + } + } + } else { + field_value = jsonResponse.getFull_table(); + baseRequestObj = CachingUtil.getCallBackCache(field_value); + } + if(baseRequestObj == null) { resultMap.put("Exception", "Oops. Something went wrong. Please make sure Callback properties are onboarded."); @@ -443,36 +494,30 @@ public class RestMusicAdminAPI { ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); } + logger.info("Going through list: "+operation+ " && List: "+jsonResponse.getUpdateList()); String key = "admin" + "." + "notification_master" + "." + baseRequestObj.getUuid(); String lockId = MusicCore.createLockReference(key); - long lockCreationTime = System.currentTimeMillis(); ReturnType lockAcqResult = MusicCore.acquireLock(key, lockId); if(! lockAcqResult.getResult().toString().equals("SUCCESS")) { - logger.info("Some other node is notifying the caller.."); + logger.error(EELFLoggerDelegate.errorLogger, "Some other node is notifying the caller..: "); } logger.info(operation+ ": Operation :: changeValue: "+changeValueMap); if(operation.equals("update")) { String notifyWhenChangeIn = baseRequestObj.getNotifyWhenChangeIn(); // conductor.plans.status - logger.info("**********notifyWhenChangeIn: "+notifyWhenChangeIn); if(field_value.equals(notifyWhenChangeIn)) { - logger.info("********** notifyting the endpoint: "+baseRequestObj.getApplicationNotificationEndpoint()); notifyCallBackAppl(jsonResponse, baseRequestObj); } } else if(operation.equals("delete")) { String notifyWhenDeletesIn = baseRequestObj.getNotifyWhenDeletesIn(); // conductor.plans.status - logger.info("**********notifyWhenDeletesIn: "+notifyWhenDeletesIn); if(field_value.equals(notifyWhenDeletesIn)) { - logger.info("********** notifyting the endpoint: "+baseRequestObj.getApplicationNotificationEndpoint()); notifyCallBackAppl(jsonResponse, baseRequestObj); } } else if(operation.equals("insert")) { String notifyWhenInsertsIn = baseRequestObj.getNotifyWhenInsertsIn(); // conductor.plans.status - logger.info("**********notifyWhenInsertsIn: "+notifyWhenInsertsIn); if(field_value.equals(notifyWhenInsertsIn)) { - logger.info("********** notifyting the endpoint: "+baseRequestObj.getApplicationNotificationEndpoint()); notifyCallBackAppl(jsonResponse, baseRequestObj); } } @@ -481,7 +526,7 @@ public class RestMusicAdminAPI { e.printStackTrace(); logger.info("Exception..."); } - logger.info(">>> callback is completed. Notification was sent from Music..."); + logger.info(EELFLoggerDelegate.applicationLogger, "callback is completed. Notification was sent from Music..."); return Response.status(Status.OK).entity(resultMap).build(); } @@ -493,7 +538,7 @@ public class RestMusicAdminAPI { String password = baseRequestObj.getApplicationPassword(); JsonNotification jsonNotification = constructJsonNotification(jsonResponse, baseRequestObj); jsonNotification.setOperation_type(jsonResponse.getOperation()); - logger.info("Response sent is: "+jsonNotification); + logger.info(EELFLoggerDelegate.applicationLogger, "Notification Response sent is: "+jsonNotification); WebResource webResource = client.resource(endpoint); String authData = username+":"+password; byte[] plainCredsBytes = authData.getBytes(); @@ -506,37 +551,39 @@ public class RestMusicAdminAPI { .post(ClientResponse.class, jsonNotification); } catch (com.sun.jersey.api.client.ClientHandlerException chf) { boolean ok = false; - logger.info("Is Service down?"); + logger.info(EELFLoggerDelegate.applicationLogger, "Is Service down?"); long now= System.currentTimeMillis(); long end = now+notifytimeout; while(! ok) { - logger.info("retrying since error in notifying callback.."); + logger.info(EELFLoggerDelegate.applicationLogger, "retrying since error in notifying callback.."); try { response = webResource.header("Authorization", "Basic " + base64Creds).accept("application/json").type("application/json") .post(ClientResponse.class, jsonNotification); if(response.getStatus() == 200) ok = true; }catch (Exception e) { - System.err.println("Is response null: "+response==null); - System.err.println("Retry until "+(end-System.currentTimeMillis())); + logger.info(EELFLoggerDelegate.applicationLogger, "Retry until "+(end-System.currentTimeMillis())); if(response == null && System.currentTimeMillis() < end) ok = false; else ok = true; try{ Thread.sleep(notifyinterval); } catch(Exception e1) {} } } } - response.bufferEntity(); - String responseStr = response.getEntity(String.class); - logger.info(">>>>> Response from Notified client: "+responseStr); + if(response == null) { + logger.error(EELFLoggerDelegate.errorLogger, "Can NOT notify the caller as caller failed to respond.."); + return; + } + JsonNotifyClientResponse responseStr = response.getEntity(JsonNotifyClientResponse.class); + logger.info(EELFLoggerDelegate.applicationLogger, "Response from Notified client: "+responseStr); if(response.getStatus() != 200){ long now= System.currentTimeMillis(); long end = now+30000; while(response.getStatus() != 200 && System.currentTimeMillis() < end) { - logger.info("retrying since error in notifying callback.."); + logger.info(EELFLoggerDelegate.applicationLogger, "retrying since error in notifying callback.."); response = webResource.header("Authorization", "Basic " + base64Creds).accept("application/json").type("application/json") .post(ClientResponse.class, jsonNotification); } - logger.error("Exception while notifying.. "+response.getStatus()); + logger.info(EELFLoggerDelegate.applicationLogger, "Exception while notifying.. "+response.getStatus()); } } @@ -556,25 +603,22 @@ public class RestMusicAdminAPI { TableMetadata tableInfo = MusicCore.returnColumnMetadata(tableArr[0], tableArr[1]); DataType primaryIdType = tableInfo.getPrimaryKey().get(0).getType(); String primaryId = tableInfo.getPrimaryKey().get(0).getName(); - logger.info(">>>>>>> Primary Id: "+primaryId); Map responseBodyMap = baseRequestObj.getResponseBody(); - Set keySet = responseBodyMap.keySet(); - /*for (Map.Entry entry : valuesMap.entrySet()) { - DataType colType = null; - try { - colType = tableInfo.getColumn(entry.getKey()).getType(); - } catch(NullPointerException ex) { - - } - }*/ + for (Entry entry : new HashSet<>(responseBodyMap.entrySet())) { + String trimmed = entry.getKey().trim(); + if (!trimmed.equals(entry.getKey())) { + responseBodyMap.remove(entry.getKey()); + responseBodyMap.put(trimmed, entry.getValue()); + } + } - - String cql = "select "; - for(String keys: keySet) { + Set keySet = responseBodyMap.keySet(); + String cql = "select *"; + /*for(String keys: keySet) { cql = cql + keys + ","; - } - cql = cql.substring(0, cql.length()-1); + }*/ + //cql = cql.substring(0, cql.length()-1); cql = cql + " FROM "+fullNotifyArr[0]+" WHERE "+primaryId+" = ?"; logger.info("CQL in constructJsonNotification: "+cql); PreparedQueryObject pQuery = new PreparedQueryObject(); @@ -583,20 +627,51 @@ public class RestMusicAdminAPI { Row row = MusicCore.get(pQuery).one(); Map newMap = new HashMap<>(); if(row != null) { - for(String keys: keySet) { - String value = null; - logger.info("responseBodyMap: "+responseBodyMap.toString()); - logger.info(">>>>>>>> converting <<<<<<<<<<<< "+keys + " : "+responseBodyMap.get(keys)+ ":" +responseBodyMap.get(keys).equals("uuid")); - if(responseBodyMap.get(keys).equals("uuid")) - value = row.getUUID(keys).toString(); - else if (responseBodyMap.get(keys).equals("text")) - value = row.getString(keys); - /*else if (responseBodyMap.get(keys).contains("int")) - value = row.getLong(keys).toString();*/ - newMap.put(keys, value); + ColumnDefinitions colInfo = row.getColumnDefinitions(); + for (Definition definition : colInfo) { + String colName = definition.getName(); + if(keySet.contains(colName)) { + DataType colType = definition.getType(); + Object valueObj = MusicCore.getDSHandle().getColValue(row, colName, colType); + Object valueString = MusicUtil.convertToActualDataType(colType, valueObj); + logger.info(colName+" : "+valueString); + newMap.put(colName, valueString.toString()); + keySet.remove(colName); + } + } + } + if(! keySet.isEmpty()) { + Iterator iterator = keySet.iterator(); + while (iterator.hasNext()) { + String element = iterator.next(); + newMap.put(element,"COLUMN_NOT_FOUND"); } } - if("delete".equals(jsonResponse.getOperation())) { + + /*if(row != null) { + for(String keys: keySet1) { + String value = null; + try { + logger.info(">>>>>>>> converting <<<<<<<<<<<< "+keys + " : "+responseBodyMap.get(keys)); + if(responseBodyMap.get(keys).equals("uuid")) + value = row.getUUID(keys.trim()).toString(); + else if (responseBodyMap.get(keys).equals("text")) + value = row.getString(keys.trim()); + else if (responseBodyMap.get(keys).equals("int")) + value = String.valueOf(row.getInt(keys.trim())); + else if (responseBodyMap.get(keys).equals("bigint")) + value = String.valueOf(row.getLong(keys.trim())); + } catch (Exception e) { + newMap.put(primaryId, pkValue); + logger.info("Error in constructJsonNotification: Invalid column.."); + } + else if (responseBodyMap.get(keys).contains("int")) + value = row.getLong(keys).toString(); + newMap.put(keys.trim(), value); + } + }*/ + + if("delete".equals(jsonResponse.getOperation()) || newMap.isEmpty()) { newMap.put(primaryId, pkValue); } jsonNotification.setResponse_body(newMap); @@ -606,30 +681,39 @@ public class RestMusicAdminAPI { return jsonNotification; } - private JsonCallback constructJsonCallbackFromCache(String fullTable) throws Exception{ + private void constructJsonCallbackFromCache() throws Exception{ PreparedQueryObject pQuery = new PreparedQueryObject(); - JsonCallback jsonCallback = new JsonCallback(); + JsonCallback jsonCallback = null; + List notifyList = new java.util.ArrayList<>(); String cql = "select id, endpoint_userid, endpoint_password, notify_to_endpoint, notify_insert_on," - + " notify_delete_on, notify_update_on, request from admin.notification_master where notifyon = ? allow filtering"; + + " notify_delete_on, notify_update_on, request, notifyon from admin.notification_master allow filtering"; pQuery.appendQueryString(cql); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), fullTable)); - logger.info("Query: "+pQuery.getQuery() + " : "+fullTable); + //pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), fullTable)); + logger.info("Query: "+pQuery.getQuery()); - Row row = MusicCore.get(pQuery).one(); - if(row != null) { + ResultSet rs = MusicCore.get(pQuery); + Iterator it = rs.iterator(); + while (it.hasNext()) { + Row row = (Row) it.next(); String endpoint = row.getString("notify_to_endpoint"); String username = row.getString("endpoint_userid"); - String password = row.getString("endpoint_password"); + ByteBuffer passwordBytes = row.getBytes("endpoint_password"); String insert = row.getString("notify_insert_on"); String delete = row.getString("notify_delete_on"); String update = row.getString("notify_update_on"); String request = row.getString("request"); + String notifyon = row.getString("notifyon"); String uuid = row.getUUID("id").toString(); + notifyList.add(notifyon); + jsonCallback = new JsonCallback(); jsonCallback.setApplicationNotificationEndpoint(endpoint); - jsonCallback.setApplicationPassword(password); + + Charset charset = Charset.forName("ISO-8859-1"); + String decodedPwd = charset.decode(passwordBytes).toString(); + jsonCallback.setApplicationPassword(decodedPwd); jsonCallback.setApplicationUsername(username); - jsonCallback.setNotifyOn(fullTable); + jsonCallback.setNotifyOn(notifyon); jsonCallback.setNotifyWhenInsertsIn(insert); jsonCallback.setNotifyWhenDeletesIn(delete); jsonCallback.setNotifyWhenChangeIn(update); @@ -648,10 +732,12 @@ public class RestMusicAdminAPI { } logger.info("After parsing. Saved request_body: "+responseBody); jsonCallback.setResponseBody(responseBody); + logger.info("Updating Cache with updateCallBackCache: "+notifyon+ " :::: "+jsonCallback); + CachingUtil.updateCallBackCache(notifyon, jsonCallback); } - return jsonCallback; + CachingUtil.updateCallbackNotifyList(notifyList); } - + @POST @Path("/onboardCallback") @Produces(MediaType.APPLICATION_JSON) @@ -665,25 +751,30 @@ public class RestMusicAdminAPI { String endpoint = jsonNotification.getEndpoint(); String notify_field = jsonNotification.getNotify_field(); Map responseBody = jsonNotification.getResponse_body(); + String triggerName = jsonNotification.getTriggerName(); + if(triggerName == null || triggerName.length() == 0) + triggerName = "MusicTrigger"; + + /*JsonCallback callBackCache = CachingUtil.getCallBackCache(notify_field); + if(callBackCache != null) { + resultMap.put("Exception", "The notification property has already been onboarded."); + return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); + }*/ String[] allFields = notify_field.split(":"); String inserts = null; String updates = null; String deletes = null; + String tableName = null; if(allFields.length >= 2) { inserts = updates = notify_field; } else if(allFields.length == 1) { inserts = deletes = notify_field;; } - + tableName = allFields[0]; + String cql = "CREATE TRIGGER IF NOT EXISTS musictrigger ON "+tableName+" Using '"+triggerName+"'"; PreparedQueryObject pQuery = new PreparedQueryObject(); - /*if (username == null || password == null || endpoint == null) { - logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGINFO, - ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); - resultMap.put("Exception", - "Please check the request parameters. Some of the required values are missing."); - return Response.status(Status.BAD_REQUEST).entity(resultMap).build(); - }*/ + String uuid = CachingUtil.generateUUID(); try { pQuery.appendQueryString( @@ -691,14 +782,16 @@ public class RestMusicAdminAPI { + "notifyon, notify_insert_on, notify_delete_on, notify_update_on, request, current_notifier) VALUES (?,?,?,?,?,?,?,?,?,?)"); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), username)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); + Charset charset = Charset.forName("ISO-8859-1"); + ByteBuffer decodedPwd = charset.encode(password); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.blob(), decodedPwd.array())); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), endpoint)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), notify_field)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), inserts)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), deletes)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), updates)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), responseBody)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), "UNKNOWN")); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), MusicCore.getMyHostId())); MusicCore.nonKeyRelatedPut(pQuery, MusicUtil.EVENTUAL); JsonCallback jsonCallback = new JsonCallback(); jsonCallback.setUuid(uuid); @@ -712,6 +805,10 @@ public class RestMusicAdminAPI { jsonCallback.setResponseBody(responseBody); CachingUtil.updateCallBackCache(notify_field, jsonCallback); logger.info("Cache updated "); + pQuery = new PreparedQueryObject(); + pQuery.appendQueryString(cql); + ResultType nonKeyRelatedPut = MusicCore.nonKeyRelatedPut(pQuery, MusicUtil.EVENTUAL); + logger.info(EELFLoggerDelegate.applicationLogger, "Created trigger"); //callBackCache.put(jsonCallback.getApplicationName(), jsonMap); } catch (InvalidQueryException e) { logger.error(EELFLoggerDelegate.errorLogger,"Exception callback_api table not configured."+e.getMessage()); diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index fe7f54ae..b75fcd85 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -259,12 +259,13 @@ - - - + + + + diff --git a/version.properties b/version.properties old mode 100644 new mode 100755 index be1ffe50..bcb19409 --- a/version.properties +++ b/version.properties @@ -4,7 +4,7 @@ major=3 minor=0 -patch=13 +patch=15 base_version=${major}.${minor}.${patch} -- cgit 1.2.3-korg